我举了以下例子来说明我的问题:
class Base
{
public:
virtual void do()=0;
}
class A: public Base
{
public:
void do();
};
class B: public Base
{
public:
void do();
}
class AB: public Base
{
public:
void do()
{
a_.do();
// if not succeed
{
b_.do();
}
}
private:
A a_;
B b_;
}
从上面的代码中,我们可以看到类A, B
和AB
来自同一个Base类。但是,类AB
需要调用类A
和类B
。这是我的问题:班级AB
的潜在问题是什么?还有其他选择吗?
另一种选择可能是:
class Base
{
public:
virtual void do()=0;
}
class A: public Base
{
public:
void do();
};
class B: public Base
{
public:
void do();
}
class AB: public A
{
public:
void do()
{
A::do();
// if not succeed
{
b_.do();
}
}
private:
B b_;
}
答案 0 :(得分:3)
AB类的潜在问题是什么?
我不知道您的设计必然会出现任何众所周知的问题。你应该问问自己"为什么会出现问题?"。
还有其他选择吗?
有很多选择。例如,A
和B
都不包含任何状态,因此您也可以停止使用类来支持自由函数,并用函数指针替换动态绑定。
为了能够比较不同的替代方案,您应首先确定您要解决的问题。
答案 1 :(得分:3)
我不知道你真正想要实现的目标。但是如果你的所有类只应该有一个来自Base的实例数据副本,那么你需要一个虚拟Base类。
你在AB的第一个例子中的问题是,你有三个!类Base的数据。一个来自继承Base,一个是成员B的一部分,它本身来自Base,而来自成员A.这是你想要的吗?
我给你以下剪辑,看看如何在所有类实例中使用Base的精确副本。也许这就是你想得到的?
我向Base添加了一些数据,以了解在使用虚拟基类时构造是如何工作的。重要的是不会从直接继承的类的构造函数中调用基类构造函数!您需要直接从最外层的构造函数调用构造函数,如AB类构造函数所示!
作为评论:只有在没有其他适合设计的情况下才应使用虚拟基类。通常,对这种解决方案的需求显示出设计问题。但是一如既往地编程:如果这完全符合您的需求,那么技术上绝对可以做到。
class Base
{
private:
std::string text;
public:
Base( const std::string& str ): text(str) {}
virtual void Do() { std::cout << text << std::endl; }
};
class A: virtual public Base
{
public:
A():Base("Default from A") {}
void FuncA() { std::cout << "FuncA" << std::endl; }
void Do() { std::cout << "Via A" << std::endl; Base::Do();}
};
class B: virtual public Base
{
public:
B(): Base ("Default from B") {}
void FuncB() { std::cout << "FuncB" << std::endl; }
};
class AB: public A,B
{
public:
//Important to know that init of Base MUST be done from here and not from A nor B !!
AB( const std::string &s): Base(s) {}
void Do() { std::cout << "Via AB" << std::endl; Base::Do(); A::Do(); B::Do();}
};
int main()
{
A a;
a.Do();
std::cout << "####" << std::endl;
B b;
b.Do();
std::cout << "####" << std::endl;
AB ab("Hallo");
ab.Do();
std::cout << "####" << std::endl;
}
答案 2 :(得分:-1)
你应该继承A和B而不是Base,因为A和B已经这样做了。