关于C++中的私有继承

s1ag04yj  于 2023-07-01  发布在  其他
关注(0)|答案(2)|浏览(176)

为什么我不能从一个类和另一个类中私有地派生一个类,而这个类是从另一个类中派生的。所以,我有以下的

class Money
{
public:
    void get() {std::cin >> amount;} 
private:
    float amount;
}

class Employee
{
public:
    void get() {std::cin >> lastName;} 
private:
    std::string lastName;
}

class Manager : public Employee, private Money  //money is used to store a wage
{
public:
    void get() {Employee::get(); Money::get();} 
}

class Executive : public Manager, private Money  // money is used to store additional bonuses
//warning :direct base 'Money' inaccessible in 'Executive' due to ambiguity  
{
public:
    void get() {Manager::get(); Money::get();}
}

我期望在Executive类中,Manager::get()将调用Money::get()来保存工资,而另一个Money::get()将保存额外的奖金。
就我目前所知,私有继承可以作为一种组合形式应用,或者当基类的接口应该对外部人员隐藏时应用,但在实现被派生的类时很有用。我明白在这种特殊情况下,组合就是我所需要的全部,但是,我不明白编译器警告我什么样的歧义,因为私有继承不允许外部类或私有派生类的子类利用这种关系

hgc7kmma

hgc7kmma1#

当你从C++中的一个类继承时,这意味着你的类包含该基类作为子类(例如Money)及其所有成员。当这个派生类的派生类再次从Money继承时,它不会重用这个子类,而是获得自己的子类。发生的是:

class Manager : public Employee, private Money
// means structurally:
Manager {
    Employee { ... }
    Money { ... }
    ...
}

// and
class Executive : public Manager, private Money
// means structurally
Executive {
    Manager {
        Employee { ... }
        Money { ... }
        ...
    }
    Money { ... }
    ...
}

问题是Executive现在在其类层次结构中有两个Money的示例:

  • Executive::Money
  • Executive::Manager::Money

这是编译器警告您的歧义。

解决方案A -复合优于继承

如果你仔细想想,ManagerMoney继承是没有意义的,因为这意味着Manager * 是 * Money的示例。如果一个Manager * 有 * Money,这将更有意义:

class Manager {
protected:
    Money money;
public:
    ...
};

class Executive : public Manager { ... };

由于Manager::moneyprotected数据成员,因此派生类(如Executive)将能够使用它。

方案B -protected继承

  • 免责声明:*不要在这里使用继承,这显然是错误的。但如果你非常坚持,这里是解决方案:

最实用的解决方案是使用protected继承。外部世界仍然无法访问Money,但Executive可以:

// protected inheritance makes Money available to derived classes
class Manager : public Employee, protected Money { ... };

// don't inherit Money again, use Manager::Money
class Executive : public Manager { ... };
nqwrtyyt

nqwrtyyt2#

我使用“otherpart”替换Executive::get()::Money::get()
因此,如果您只想添加一个字符串,则无需担心派生

#include<iostream>

class Money
{
public:
    // void get() {std::cin >> amount;} 
    void out() {std::cout << amount <<" " << otherpart<<std::endl;};
    virtual void get() {std::cin >> amount >> otherpart;};
private:
    std::string amount;
    std::string otherpart;
};

class Employee
{
public:
    void get() {std::cin >> lastName;}
    void out() {std::cout << lastName<<std::endl;};
private:
    std::string lastName;
};

class Manager : public Employee, private Money  //money is used to store a wage
{
public:
    void get() {Employee::get(); Money::get();}
    void out() {Employee::out(); Money::out();}
};

class Executive : public Manager, private Money  // money is used to store additional bonuses
//warning :direct base 'Money' inaccessible in 'Executive' due to ambiguity
{
public:
    void get() {Manager::get();}
    void out() {Manager::out();}
};

int main(void) {
    Executive compen = Executive();
    compen.get();
    compen.out();
    return 0;
}

相关问题