5

I have a class that is derived from another, I use an array of base class pointers to hold instances of the derived class, but because the array is of the base class, I cannot access members belonging to the derived class with pointer notation, is it possible for me to access these members with a simple command or should I just rewrite my base class to define the member and only use it in the derived class?

Example:

class A {
public:
    int foo;
};

class B : public A {
public:
    char bar;
};

class C : public A {
    int tea;
};

int main() {
    A * arr[5];
    arr[0] = new B;

    char test = arr[0]->bar; //visual studio highlights this with an error "class A has no member bar"

    return 0;
}
Stephen
  • 1,498
  • 17
  • 26
  • 1
    As far as I know you cannot access member of a derived class from pointer of a base class. Simply because base class doesn't recognize it in anyway. You can however access member of base class from pointer of a derived class because hierarchy says **public members of base class are now also members of derived class**. –  Apr 10 '16 at 02:22
  • But the data technically exists right? Could I use memory offset to do it? – Stephen Apr 10 '16 at 02:23
  • 2
    This is what virtual methods are for. If you haven't yet learned about virtual methods in your C++ class, now is an excellent opportunity to do so. – Sam Varshavchik Apr 10 '16 at 02:27
  • Possible duplicate of [C++ Access derived class member from base class pointer](https://stackoverflow.com/questions/2436125/c-access-derived-class-member-from-base-class-pointer) – 1201ProgramAlarm Aug 09 '18 at 01:39

3 Answers3

6

I cannot access members belonging to the derived class with pointer notation

This is by design: you did not tell the compiler that the object pointed to by the pointer is of the derived type.

is it possible for me to access these members with a simple command

You can do it if you perform static_cast<B*>(arr[0]) if you are 100% certain that the pointer points to B, but casting solution should be used as the last resort. Instead, you should derive a member function in the base class, and provide an implementation in the derived class:

class A {
public:
    int foo;
    virtual char get_bar() = 0;
};

class B : public A {
    char bar;
public:
    char get_bar() {
        return bar;
    }
};
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • The way I designed my algorithm, I will always know when the pointer points to the derived class. So this works perfectly for what I need. I tried a dynamic cast but I didnt think about doing a static cast, thank you. I am marking this as the answer. – Stephen Apr 10 '16 at 04:18
  • You have accepted the answer for all the wrong reasons. You should seriously consider using a virtual function. – n. m. could be an AI Apr 10 '16 at 07:18
  • This question was for one program, most of which had already been written. I needed this specific answer as a quick fix. In the future I will definitely use virtual functions to get the job done. – Stephen Apr 10 '16 at 21:26
  • Virtual functions should also be defined and used for the right reasons. In my opinion, this was not the case and the solution offered in this answer leads to a very weak OOP approach. A better approach starts with the right questions about a specific program, rather than applying thoughtless rules of thumbs dogmatically. In this program (OP's), I'd start with the question: If you knew you need `bar`, why then did you keep the `B` object in an `A` pointer from the first place? The answer to this question could point out the correct direction to redesign the program. – R.G. Apr 11 '16 at 01:22
1

Read about type-casting, it's a very basic and important aspect of the language.

In short, you can always cast a pointer-to-base to a pointer-to-derived, then refer to its unique public members.

A * arr[5];
arr[0] = new B;

char test = static_cast<B*>(arr[0])->bar;

However, the last line above is a valid statement even if that A* doesn't really point to an object of B type. If you try that on a C object, it will compile, and result in undefined behavior during runtime.

It should be mentioned however, that usually when one cannot be certain of the type of the object he refers to, a better design of the program could have prevented it from the first place. A common claim says that it is true for type casting in general.

P.S. Note that in your code, bar is a private member of class B (unintentionally, I assume. Any member of a class is private by default), hence cannot be accessed anyway outside of class B implementation.

R.G.
  • 116
  • 4
  • Casting is not the right tool for the job, and it is not a basic aspect if object-oriented programming paradigm, which is more important than any particular language. Please don't use casting to cover up for inadequate OO design. – n. m. could be an AI Apr 10 '16 at 03:09
  • I believe this is debatable. And for my understanding, this question wasn't about OOD. It was a technical question, and type casting is the straightforward answer for the question in the way it was formed. If you know a "right tool for the job" which doesn't change the topic, please do. – R.G. Apr 10 '16 at 03:31
  • "I believe this is debatable". I don't. "It was a technical question". It was a question by somebidy who needs guidance, not technically correct but dangerous answers. – n. m. could be an AI Apr 10 '16 at 03:46
  • "If you know a "right tool for the job" which doesn't change the topic, please do". There's already an answer that describes one. – n. m. could be an AI Apr 10 '16 at 03:51
  • So, defining an arbitrary virtual function at the base class, just for the purpose of accessing a very specific member of a very specific derived class, a member which obviously should not even be _known_ by the base class nor by other unrelated derived classes, and all that in order to avoid downcasting. If that's what you would call OOD, I guess that's another topic we don't see eye to eye. – R.G. Apr 10 '16 at 14:11
  • No, this is absolutely not what I call OOD. I cannot find anything remotely similar anywhere in my words. Downcasting by itself is not important. Accessing a member which obviously should not even be known by the base class nor by other unrelated derived classes **nor by anyone else** is a problem. If you agree that the member can be known by outsiders, then there's nothing wrong with it being known by the base class (just another outsider), right? – n. m. could be an AI Apr 10 '16 at 14:36
  • My comment exceeded the allowed comment length here, so I take this hint to realize that this is probably not the place for such discussions, and we'll probably have to agree to disagree. :) – R.G. Apr 10 '16 at 15:04
0

In case of your code, your member of derived class is private. So, you can not access it from base class. If you want to access, you must change the member of derived class to "public". You should fix your code like this:

class B : public A {
public:
    char bar;
};

int main() {
A * arr[5];
arr[0] = new B;

char test = static_cast <B *>(arr[0])->bar; //visual studio highlights this with an error "class A has no member bar"
return 0;

}