我有:
class A {
virtual void foo() = 0;
virtual void bar() = 0;
};
class Fooing {
virtual void foo() = 0;
};
class Barring {
virtual void bar() = 0;
};
class TallFooing : public Fooing {
void foo(){ std::cout << "tall foo" << std::endl; }
};
class ShortFooing : public Fooing {
void foo(){ std::cout << "short foo" << std::endl; }
};
class BlueBarring : public Barring {
void bar() { std::cout << "blue bar" << std::endl; }
};
class RedBarring : public Barring {
void bar() { std::cout << "red bar" << std::endl; }
};
template <typename S, typename T>
class B : public A, public S, public T { };
int main() {
A* a1 = new B<TallFooing, RedBarring>();
A* a2 = new B<ShortFooing, BlueBarring>();
a1->foo(); a1->bar();
a1->foo(); a2->bar();
};
在Barring课程中混合使用“好主意”(TM)?我做得对吗?如果没有,你能否建议做同样的替代/改进?
另外,以下内容如下:
class Fooing {
virtual void foo() = 0;
};
class Barring {
virtual void bar() = 0;
};
class A : public virtual Fooing, public virtual Barring { };
class TallFooing : public Fooing {
void foo(){ std::cout << "tall foo" << std::endl; }
};
class ShortFooing : public Fooing {
void foo(){ std::cout << "short foo" << std::endl; }
};
class BlueBarring : public Barring {
void bar() { std::cout << "blue bar" << std::endl; }
};
class RedBarring : public Barring {
void bar() { std::cout << "red bar" << std::endl; }
};
template <typename S, typename T>
class B : public virtual A, public S, public T { };
和main()
相同?
备注:
foo()
和bar()
确实是独立的,任何组合都可以。也就是说,什么都不会破坏。答案 0 :(得分:1)
您的代码无法编译(即使我修复了语法错误)。 B
的实例化是抽象的,因为它们派生自A
,它具有纯虚函数并且不实现它们。来自一个父级的同名函数不实现另一个父级的纯虚函数。
您可以使用您的模板方法在A
中实现B
(为简洁起见,我使用struct,您的代码尝试访问类外的私有成员):
template<class S, class T>
struct B: A, S, T {
void foo() {
this->S::foo();
}
void bar() {
this->T::bar();
}
};
或许更常见的方法是使用虚拟继承。根据其他接口定义A
可能是有意义的:
struct A: virtual Fooing, virtual Barring {
注意虚拟的使用。这将为您提供评论中提到的钻石。为了使编译器在单独的接口中建立foo
之间的连接,这是必要的。您还必须在所有实现类中进行虚拟继承:
struct TallFooing: virtual Fooing {
这些更改应该使您的代码编译。多个/虚拟继承是一个好主意是非常基于意见。将它用于纯虚拟接口以外的任何东西通常都是不受欢迎的。
另外,请将接口类的析构函数设为private或将其声明为virtual。否则你可能最终会泄漏代码(编译器可能会注意到这一点)。
答案 1 :(得分:0)
我修复了所有可能的编译错误(缺少包含,缺少public
),但是子类B
仍然没有补充{{1}和A::foo
所以即使这样程序也无法编译。你不能在C ++中使用多重继承来以这种方式实现抽象接口。