自动引用会话继承

automatic reference conversation inheritance

本文关键字:继承 会话 引用      更新时间:2023-10-16

我试图完全理解OOP中的继承。所以,我做了一些尝试。但是,有两点我被卡住了,其中一个是object slicing。另一个是调用析构函数的顺序。为什么Box {carton}需要正确的复制ctor?如果加了Box {carton},纸箱型怎么能转换成箱式(我完全不明白)。

// right ctor
/*
Carton(const Carton& carton) : Box {carton}, material {carton.material}
{ std::cout << "Carton copy constructor" << std::endl; }
*/

代码:

#include <iomanip>
#include <iostream>
#include <string>
using namespace std;
class Box
{
protected:
    double length;
    double width;
    double height;
public:
    // Constructors
    Box(double lv, double wv, double hv);
    Box(double side) : Box {side, side, side}
    { std::cout << "Box(double) called.n"; }
    Box() { std::cout << "Box() called.n"; }
    double volume() const
    { return length * width * height; }
    double getLength() const { return length; }
    double getWidth() const { return width; }
    double getHeight() const { return height; }
    ~Box()
    { cout << "box destructor" << endl; }
    void print();
    // copy ctor
    Box(const Box& box) : length{box.length}, width{box.width}, height{box.height}
    { std::cout << "Box copy constructor" << std::endl; }
};

class Carton : public Box
{
private:
    string material {"Cardboard"};
public:
    Carton(double lv, double wv, double hv, const string desc) : Box {lv, wv, hv}, material {desc}
    { std::cout << "Carton(double,double,double,string) called.n";}
    Carton(const string desc) : material {desc}
    { std::cout << "Carton(string) called.n";}
    Carton(double side, const string desc) : Box::Box(side),material {desc}
    { std::cout << "Carton(double,string) called.n";}
    Carton() { std::cout << "Carton() called.n";}
    ~Carton()
    { cout << "cartoon destructor" << endl; }
    void print();
    // right ctor
    /*
    Carton(const Carton& carton) : Box {carton}, material {carton.material}
    { std::cout << "Carton copy constructor" << std::endl; }
    */
    Carton(const Carton& carton) : material {carton.material}
    { std::cout << "Carton copy constructor" << std::endl; }
};
int main()
{
    // Declare and initialize a Carton object
    Carton carton(20.0, 30.0, 40.0, "Glassine board");
    Carton cartonCopy(carton);             // Use copy constructor
}
// Ctor
Box::Box(double lv, double wv, double hv) : length {lv}, width {wv}, height {hv}
{ std::cout << "Box(double, double, double) called.n"; }
// Redefinitions
void Box::print()
{
    cout << "Box printttttt" << endl;
}
void Carton::print()
{
    cout << "Carton printttttt" << endl;
}

请记住,继承是一种"is a"关系。CartonBox,这就是为什么当需要Box时可以使用Carton

但是要小心对象切片问题。如果函数按值接受Box参数,并且传递Carton对象,则该函数将仅获得Box部分。


此外,您还有另一个问题,即您的print函数不是virtual。这意味着,即使您有一个指向Box的指针或引用并传递了一个Carton,也不会调用Carton::print函数。

让我们用一个例子来说明这一点:

void foo(Box const& box)
{
    box.print();
}
int main()
{
    Carton carton(...);
    foo(carton);
}

上面的示例代码不会有任何对象切片问题,因为foo函数会获得对基类的引用。但是,它将打印

方框打印ttttt

如果您制作Box::print虚拟

virtual void print();

然后上面的代码将打印

纸箱打印ttttt