4

I am writing a code in C++ right now, and I have a dilemma.

EDIT: I added the class relevant definition


  • _fullName is defined in the class as a private dm(char _fullName)

my class contains the getter method below:

char* getFullName() const { return this->_fullName; }

However, I had in the past cases in which I returned char* with const(const char*)
I can change the getter method to this one:

const char* getFullName() const { return this->_fullName; }

Both versions are compiling but I don't know how to choose. I would take the second version, but I wonder
Why even the version without the const is compiling? shouldn't it give an error when I remove the const keyword, because the function is a CONST member function and therefore the dms are const as well and cannot be returned without the const keyword???

This is the class relevant definition:

class Professional
{
private:
    char* _ID;
    char* _fullName;
    int _age;
    char* _profession;
}
  • 3
    Can’t you simply return a std::string? – Macmade Sep 04 '20 at 17:29
  • By the way, there’s no issue returning a non const value from a const method. – Macmade Sep 04 '20 at 17:30
  • of course I can but I want to deeply understand the char* issue – CodeLearner Sep 04 '20 at 17:30
  • The pointer is what you are returning. And you are returning it by value. – drescherjm Sep 04 '20 at 17:30
  • @Macmade, if there is no issue then why is this an error? class A{ int num; int* func(const int* anyInt) const{return #} – CodeLearner Sep 04 '20 at 17:31
  • @drescherjm but i want to return the address so therefore char* type... – CodeLearner Sep 04 '20 at 17:34
  • When you put `const` after the method name, that means that the method will not change the state of the instantiated class. – Andy Sep 04 '20 at 17:35
  • I think where the confusion is that using the returned pointer you could change the contents of c-string that the pointer points to. – drescherjm Sep 04 '20 at 17:35
  • @CodeLearner `int` is not `char`. There are some legacy exceptions in compilers that allow passing around `const char *` as `char *` that don't apply to `const int *`. – user4581301 Sep 04 '20 at 17:37
  • 1
    @CodeLearner I am not sure this makes sense. Can you show the declaration of `_fullName` - is it a `char` or a `char *`? - you can't return _fullName if its just a char with a return type of char * or const char * - you would have to return type char or return `&this->_fullName` – code_fodder Sep 04 '20 at 17:39
  • Infact just drop the `this->` part alltogether... – code_fodder Sep 04 '20 at 17:40
  • When writing **getter** member functions like `getFullName() `, the return of a pointer to a private member is not intended to be modified, so `const char *` would be the preferred type. – David C. Rankin Sep 04 '20 at 17:44
  • 1
    This is what I expect to see: https://godbolt.org/z/v1s9o8 No `const` works, all `const` works, mixing `const` fails to compile. Your compiler may have extensions to allow older code from the days when `char` was given some special treatment. – user4581301 Sep 04 '20 at 17:47
  • Why `_ID`, `_age` instead of `ID` and `age`? – i486 Sep 04 '20 at 17:49
  • 1
    Does this answer your question? [c++ const member function that returns a const pointer.. But what type of const is the returned pointer?](https://stackoverflow.com/questions/3888470/c-const-member-function-that-returns-a-const-pointer-but-what-type-of-const) – Vargo Sep 04 '20 at 17:49
  • @user4581301 I concur with this - but this does not match what the OP is saying is happening, so I can't really see how they are getting this to compile which is odd considering the return types are `char *`/`const char *` and the item being returned is apparently a `char` (but I suspect it is not - we can't see what it is yet) – code_fodder Sep 04 '20 at 17:53
  • Basically return or pass `const` whenever you can. If there's no reason for something to be mutable, then make it `const`. The way to properly test this would be to actually use it - `char* x = z.getFullName()` vs `char const* y = z.getFullName()` – Den-Jason Sep 04 '20 at 18:06
  • @code_fodder Different compilers have different quirks and different rule exceptions and extensions. Asker's probably using an older Visual Studio or an up-to-date one with language compliance turned off. – user4581301 Sep 04 '20 at 18:08
  • i am using VS2019 – CodeLearner Sep 04 '20 at 18:11
  • @Vargo, I have already read it before posting my post, it was helpful but not in 100% – CodeLearner Sep 04 '20 at 18:16

2 Answers2

4

First understand what const attached to a member function means. It determines the const-ness of the implicit this used for the member. Given this:

struct S
{
    char value[10];

    const char *mfn() const { return value; }
};

within the confines of mfn the implicit this is const S *. Furthermore, all references to members obtained therein are also const. In this case, that means value as an expression representation is const char (&)[10] before any further conversion are attached therein.

That's important.

In the correct posted example above there is an automatic conversion to temporary pointer, since const char(&)[10] converts to const char* without objection. However, the following will fail:

struct S
{
    char value[10];

    char *mfn() const { return value; }
};

The reason this will fail is simply because there is no conversion possible. value, remember, is const char (&)[10], and can only implicitly convert to const char*.

But how could it succeed? Well, consider this:

struct S
{
    char *ptr;

    char *mfn() const { return ptr; }
};

This will work. The reason is subtle, but obvious once you think about it. ptr is a char*. The attachment of const to this makes that char * const&, not const char *& (there is a difference; the former is a reference to a non-mutable pointer to mutable data, the latter is a reference to a mutable pointer to non-mutable data). Since return ptr is not mutating ptr (or anything else in the object), it is viable as a result.

In short, in your case it works because the pointer you are returning isn't via some implicit conversion from a const underlayment; it's just a value.

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
2

You have a few things going on here, in your example of the int num member this is not the same as a char * member.

lets expand your example a bit:

class Professional
{

    int* func() const
    {
        return &myInt; // Fails because it returns a reference to a member variable
    } 

    char* func() const
    {
        return &myChar; // Fails because it returns a reference to a member variable
    } 

    int* func() const
    {
        return pInt; // ok because it returns a COPY of the member pointer
    } 

    char* func() const
    {
        return pChar; // ok because it returns a COPY of the member pointer
    } 

    int myInt;
    char myChar;
    int *pInt;
    char *pChar;

Note: the two pointers getting returned by copy are ok. Its the pointers that are copies not the thing being pointed to. The memory that is pointed to is nothing to do with this class.

As to an answer to your question: there is a rule of thumb that is to apply const as much as possible - this helps to show other users your intent and gains benefits from compiler warnings / errors if a user tries to use your class in a way you did not intend. So in this case pass back a const char *.

Note: See this answer for more specific details here: What is the difference between const int*, const int * const, and int const *?

code_fodder
  • 15,263
  • 17
  • 90
  • 167