pppploi8's Blog

欢迎来到pppploi8的个人博客!

C++ Primer学习笔记-对象转换

Java里的赋值都是引用传递的,所以习惯了…然后果然又被C++坑到了

首先很重要的问题是C++里赋值是调用的复制构造函数来对对象复制一份新的然后传递的,所以下面的代码和预想的完全不一样

class Base {
public:
    Base () {
        cout << "Base::Base()" << endl;
    }
    ~Base(){
        cout << "Base::~Base()" << endl;
    }
    virtual void print () {
        cout << "Base::pirnt()" << endl;
    }
};
class Child : public Base {
public:
    Child () {
        cout << "Child::Child()" << endl;
    }
    ~Child () {
        cout << "Child::~Child()" << endl;
    }
    void print(){
        cout << "Child::print()" << endl;
    }
};
int main() {
    Base b = Child();
    b.print();
    return 0;
}

最后输出的是

  • Base::Base()
  • Child::Child()
  • Child::~Child()
  • Base::~Base()
  • Base::pirnt()
  • Base::~Base()

因为C++的=是复制,而不是Java那样的直接传递引用,所以本质上是首先new了一个Child对象,然后调用他里面基类的复制构造函数来复制出一份Base对象,放到Base b变量中,销毁临时创建的Child对象,即输出前四个。然后调用b里的print方法,最后销毁副本b

如果希望调用到Child里的print方法,则应该传递指针或者引用,而不是复制出一份新的对象,代码如下(类部分代码相同不再重写):

int main() {
    Base *b = new Child();
    b->print();
    delete b;
    return 0;
}

输出是

  • Base::Base()
  • Child::Child()
  • Child::print()
  • Base::~Base()

看起来对了,可是Child的析构函数没有被调用,只调用了Base的析构函数,很明显不正确,这时候应该给基类的析构函数也加上virtual关键字,即 virtual ~Base();最后输出的就是

  • Base::Base()
  • Child::Child()
  • Child::print()
  • Child::~Child()
  • Base::~Base()