Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting my conceptions about pointers and references straight

I've been programming a while now at school, and I'm working on my first independent large project. I've been discovering a lot of things about programming that I haven't known before and it's been great.

However, more and more, I feel like I no longer understand C++ as a language the more I delve into it. I'd like to get some of my (mis) conceptions about references and pointers straight before continuing, and I hope that you, stackoverflow, could correct me if I'm wrong.

Thanks in advance, and here we go!

1. When converting between classes, what actually gets converted is the virtual table.

Example:

class A{
public:
    A() : x(0) {};
    int x;
    virtual void doStuff() {
        cout << x <<endl;
    }
};

class B : public A{
public:
    B() : y(1) {};
    int y;
    virtual void doStuff() {
        cout << y <<endl;
    }
};

If I had converted an object b of type B to A, what would happen internally is the virtual table of b would be discarded, and replaced with a corresponding virtual table of type A, and the destructor of y would be called because there is no longer a reference to it. Similarly, the doStuff in b would be made to point to the function address of A::doStuff instead of B::doStuff. The address pointing to x would stay the same however.

2. Which implies that the only way to take advantage of polymorphism is through pointers and references

As a consequence of point 1, the only way to take advantage of polymorphism in virtual methods of classes would be to use references and pointers, because if we passed by value, the classes itself would be automatically converted into the base class.

Example:

void doALotOfStuff(A a1, A a2) {
    a1.doStuff();
    a2.doStuff();
}

int main(){
    A a;
    B b;
    doALotOfStuff(a,b);
    return 0;
}

would print out

0
0  

because the compiler would generate code to convert b into A.

3. Furthermore, the only way to take advantage of this kind of polymorphism with arrays and STL containers would be to use pointers because references cannot be stored

Since vector would not work because references are not assignable, it follows that if I wanted to have a vector of base classes, I would need to create a vector of pointers of A in order to preserve the virtual table of elements of Type B.

Sorry if this was TL;DR, but it's be kind of bothering me for a while when I was doing some class design on my project, and I realized I couldn't really get away from just using either pointers or references because of library interfaces and polymorphism issues.

like image 724
Xzhsh Avatar asked Aug 31 '10 01:08

Xzhsh


2 Answers

While you have some nice ideas in point #1, that's not actually how it works. Conversion is not done in-place, it is done by creating a new object which copies the members it knows about from the conversion source (which is to say, the base class members, unless you have some really weird forward declarations in your base class). The instance of the derived object is not changed in any way. Of course the copy has a different memory address from the original object. Passing by value ALWAYS involves copying.

like image 57
Ben Voigt Avatar answered Oct 01 '22 11:10

Ben Voigt


  1. When you say "convert an object b of type B to A", you may mean two different things:

    • create a new object of type A that is copied from b, or
    • make a pointer of type A* or a reference of type A& that points or refers to b.

    In either case, the original object b is unchanged. You may throw it away after the conversion, but that's a different issue, and the conversion alone doesn't alter b.

    (Except in rare cases when the conversion operator or the constructor involved takes a non-const reference to B and alters the argument. However, even in this case, it's not the vtable replacement as you mentioned.)

    Once an object is created, its type doesn't change throughout its lifetime (until it is destroyed). That means, the vtable replacement you mentioned never occurs.

  2. Yes, polymorphism in C++ is achieved through pointers or references.

    Note that, in your example, a1 and a2 are copied from a and b, and the conversion did not alter a or b in any way.

  3. Yes, you're right. Or any kind of smart pointer is acceptable (or preferable).

like image 36
musiphil Avatar answered Oct 01 '22 13:10

musiphil