首页 > 解决方案 > 具有类继承和具有基类作为派生类中的数据成员之间有明显的区别吗?

问题描述

我对面向对象的范式还是有点陌生​​,因此关于 OOP 的一件事让我感到困惑。这听起来像是一个天真的问题,答案很明显,而且很可能是一个,但是以下两种情况之间有什么区别:

情况1:

class A
{
public:
    A() = default; 
    A(int i) : data_point(i) {}; 
    virtual int process_data_point();

protected: 
    int data_point=0;
};

class B : public A
{
public:
    int process_data_point() override;
};

案例2:

class A
{
int data_point=0;

public:
    A() = default; 
    A(int i) : data_point(i) {}; 
    int process_data_point();
};


class B
{
public:
    A process_data_point_in_a_different_way();
    A data_point
};

我的意思是,我知道案例 1 处理继承,这符合 OOP 的精神,但我无法摆脱这样的感觉,即只需采用基类并定义包含基数据成员的新类,也可以模拟继承类,具有一些附加功能(如案例 2 所示)。我知道从长远来看模拟继承可能最终会变得过于复杂(特别是如果最终从数据成员类中获得一些不需要的功能),但我希望对于一些简单的情况,继承模拟工作得很好。

有人可以更详细地说明这一点吗?关于仿真的想法本质上是不好的,还是在某些情况下有意义?

标签: c++oopinheritance

解决方案


差异1

在“继承”主题下还有另一个主题,称为“多态性” - 以相同方式与不同对象相关的能力。使用继承方式时,可以制作接口类,以后在多态的情况下使用。快速浏览一下这段代码:

class BaseClass {
public:
    virtual void action() = 0;
};

class A : public BaseClass {
public:
    void action() {
        cout << "A class" << endl;
    }
};

class B : public BaseClass {
public:
    void action() {
        cout << "B class" << endl;
    }
};

在这种情况下,我们有 3 个类。BaseClass 包含抽象函数“action”,以及两个继承类。以下“main”函数展示了如何以多态方式使用它们:

int main() {
    A a;
    B b;
    vector<BaseClass*> all = vector<BaseClass*>();
    all.push_back(&a);
    all.push_back(&b);

    for (size_t i = 0; i < all.size(); i++) {
        all[i]->action();
    }
}

输出将是:

A class
B class

但是看,我没有打电话a.action()b.action()- 我在一个循环中打电话给他们all[i]->action()。如果没有继承,您将无法做到这一点。

差异 2

类中的“受保护”特权仅授予类本身和继承类的访问权限。让我们看另一个例子:

class BaseClass {
private:
    void private_method() {
        cout << "Base class private method" << endl;
    }
protected:
    void protected_method() {
        cout << "Base class protected method" << endl;
    }
public:
    void public_method() {
        cout << "Base class public method" << endl;
    }
};

假设我们有这个类,其中包括private_methodprotected_methodpublic_method。现在我们有两个不同的类。继承BaseClass的类A和包含BaseClass的类B。让我们看看我们可以在每个类中使用哪些方法:

class A : public BaseClass {
public:
    void test_privileges() {
        //this->private_method();   // Compilation error!
        this->protected_method();
        this->public_method();
    }
};

class B {
private:
    BaseClass bc;

public:
    void test_privileges() {
        //bc.private_method();      // Compilation error!
        //bc.protected_method();    // Compilation error!
        bc.public_method();
    }
};

如您所见,继承类和包含它之间存在保护差异。

区别3

当您设计代码时,您希望它对每个人都尽可能清晰。为此,您必须在代码中保持逻辑流程。继承一个类和包含它之间存在逻辑差异。当你继承一个类时,你可以说继承人类是继承类,例如:

class Animal {};
class Dog : public Animal {};
class Cat : public Animal {};

Dog 是 Animal -> 所以 Dog 类必须继承 Animal 类。当您在另一个类中包含一个类时,您可以说: contains 类具有包含类,例如:

class Tail {};
class Eye {};
class Dog {
private:
    Tail tail;
    Eye eye;
};

狗有尾巴。-> 所以 Dog 类包含 Tail 类。狗有眼睛。-> 所以 Dog 类包含 Eye 类。


推荐阅读