在我的示例中,实际上有一些C 继承问题

A few C++ inheritance questions in practice on my example?

本文关键字:继承 问题 实际上 我的      更新时间:2023-10-16

我知道OOP的所有理论,但是有些事情我无法理解。假设我有一个Vector3D类,该类具有3个变量(3个坐标),并且某些操作(例如计算长度和内容)。

现在,我想构建一个将从vector3d继承的vector2D类,毕竟是相同的,第三个坐标等于0,现在我该怎么做?如何编写Vector2D的构造函数,该构造函数将构建一个vector3d的第三坐标等于0?

如果我使坐标私有我如何继承它们并将它们用作vector2d的坐标,或者即使我受到保护,这将意味着vector2d将具有其自己的独立坐标?

以下代码将实现您所描述的内容:

class Vector3D {
public:
    Vector3D(int x, int y, int z) : x_(x), y_(y), z_(z) { }
    virtual ~Vector3D() = default;
    int get_x() { return x_; }
    int get_y() { return y_; }
    int get_z() { return z_; }
    // ... other member functions ...
private:
    int x_, y_, z_;
};
class Vector2D : public Vector3D {
public:
    Vector2D(int x, int y) : Vector3D(x, y, 0) { }
    virtual ~Vector2D() = default;
};

vector3d中定义的所有成员函数都可以用于类型vector2d的对象。这也意味着,在此实施中,您可以在类型Vector2d的对象上调用get_z()

Vector2D v2d(5, 7);
int z = v2d.get_z(); // z will be 0

这可能不是您想要的。如果这是您想要的,太好了!但也请考虑以下方式:

Vector3D* ptr = new Vector2D(8, 3);

该代码是合法的,您还想允许这种情况发生吗?

顺便说一句,如果您希望vector2d对象像vector3d对象一样,从vector3d继承vector2d是:

#include <vector>
std::vector<Vector3D*> v;
v.push_back(new Vector3D(1, 2, 3));
v.push_back(new Vector2D(4, 5)); // Legal because Vector2D inherits from Vector3D
v[0]->get_z(); // = 3
v[1]->get_z(); // = 0

sidenote:切勿在生产代码中使用原始指针,而是使用std::shared_ptr<Vector3D>

如果此实施是良好的,则取决于您的需求,并且可以决定。它既有优点又有缺点。


回答您的其他问题:

如何编写vector2d的构造函数,该构造函数将构建vector3d,第三坐标等于零?

您需要使用初始化列表来调用基类的某个构造函数:

#include <iostream>
class Base {
public:
    Base(int i) {
        std::cout << "Base ctor with " << i << "n";
    }
};
class Derived : public Base {
public:
    Derived(int i, int j) : Base(i) { // Calls Base's constructor with argument 'i'
        std::cout << "Derived ctor with " << i << " and " << j << "n"; 
    }
};
int main(int argc, char** argv) {
    Derived d(1, 2);
    return 0;
}

编译并运行:

$ Base ctor with 1
$ Derived ctor with 1 and 2

初始化列表中的初始化对象将确保其各自的构造函数首先被称为。


如果我使坐标私有我如何继承它们并将它们用作vector2d的坐标,或者即使我受到保护,这将意味着vector2d将具有自己的独立坐标?

private成员仅在类本身内可访问。要允许派生的类访问它们,您需要使其成为protected(或public,但这将使每个人都可以访问!)。

class Base {
protected:
    int touch_me;
private:
    int cant_touch_me;
};
class Derived : public Base {
public:
    void foo() {
        int touch_me = 0; // Legal.
        int cant_touch_me = 1; // Illegal, will result in a compile error.
    }
private:
    int lonely;
};

类型基础的所有对象都将有两个数据成员:touch_mecant_touch_me

派生类型的所有对象都将具有三个数据成员:touch_mecant_touch_melonely。由派生声明和实现的函数只能访问touch_melonely,但是该对象确实包含所有三个!