如果一个基类有2个派生类,并且这些类每个都有一个派生类.那么我可以为大多数派生类扩展一个基方法*一次*吗
If a base class has 2 derived classes, and those classes each have a derived class, can I extend a base method *once* for the most derived classes?
很抱歉标题太冗长。以下是我正在使用的继承方案的pseduo代码,假设C++和公共继承:
ClassA
ClassB : ClassA
ClassC : ClassA
ClassBB : ClassB
ClassCC : ClassC
我想覆盖ClassA
中为ClassBB
和ClassCC
定义的方法。但我只能使用ClassBB
、ClassCC
或一个新类。
我知道我可以扩展ClassA
,但我需要更改它们的ClassB
和ClassC
的定义(进而更改ClassBB
和ClassCC
)才能看到更改。有了这个限制,我想我不得不在ClassBB
和ClassCC
中复制覆盖。有别的办法吗?
您可以实现一次全局函数模板,并在ClassBB
和ClassCC
中的重写函数的定义中调用它。那么,你只需要写一次隐含语。下面是一些未经测试的代码:
struct A
{
virtual void foo() {}
};
struct B : public A {};
struct C : public A {};
template<typename T>
void foo_impl(T const& t)
{
//do something with t
};
struct BB : public B
{
virtual void foo() { foo_impl(*this); }
};
struct CC : public C
{
virtual void foo() { foo_impl(*this); }
};
由于您尚未指定类A
中的函数是否为虚拟函数,因此我们有两种可能性。
如果foo
不是虚拟的,并且不需要将BB
与指向A
的指针一起使用(C
和CC
也是如此):
class A { public: void foo(); }
class B : public A {} // `A::foo` can be accessed from B.
class BB : public B
{
public:
// Problem (1): `A::foo` can be accesed from B, and `BB::foo` is another function.
void foo() { <other_behaviour> }
};
为了避免问题(1),您可以将A::foo
设为私有:
class A { public: void foo(); }
class B : public A {} // `A::foo` can be accesed from B.
class BB : public B
{
public:
void foo() { <other_behaviour> }
private:
using A::foo; // `A::foo` can't be accessed from B.
};
在这种情况下,您现在有两个函数:A::foo
和B::foo
,但不能从B
访问A::foo
。
如果您需要将BB::foo()
与指向A
(或B
)的指针一起使用,或者A::foo
已经是虚拟的:
class A { public: virtual void foo(); }
class B : public A {} // `A::foo` can be accessed from B.
class BB : public B
{
public:
// Problem (2): `A::foo` and `B::foo` are two different functions, but for using `A::foo`,
// the user must write `A::foo()` to call it, and don't simply `foo()`.
void foo() { <other_behaviour> }
};
要解决(2),可以执行相同的操作,将A::foo
与using
私有化。在这两种情况下,B
(和C
)都不需要更改,在第一种情况下也不需要更改A
。
如果您不需要访问基类中的任何受保护成员,只需委托给一个外部函数,可能是上一个答案中建议的模板。
否则,您可以使用多个虚拟继承:
#include <iostream>
class Base
{
public:
virtual void foo() {std::cerr << "Base::foo: " << (++i) << std::endl;};
Base() : i(0) {}
virtual ~Base() {}
protected:
int i; // the state that you need to access in foo()
};
class Implement: public virtual Base
{
public:
void foo() override {std::cerr << "Implement::foo: " << (++i) << std::endl;}
};
class D1: public Base{};
class D2: public Base{};
class DD1: public D1, public Implement
{
public:
virtual void foo() override {Implement::foo();}
};
class DD2: public D2, public Implement
{
public:
virtual void foo() override {Implement::foo();}
};
int main()
{
DD1 dd1;
dd1.foo();
D1 &d1r = dd1;
d1r.foo();
D1 d1;
d1.foo();
}
一个限制是,您的DD1和DD2实例最终会有一个不明确的基类
广告由@Ben Voigt建议,CRPT是一个很好的替代方案,可以在不受模糊基类限制的情况下解决相同的问题:
template <class D>
class CRTP
{
protected:
void foo_impl(D &d) {std::cerr << "CRTP::foo_impl: " << (++d.i) << std::endl;}
};
class DD2: public D2, public CRTP<DD2>
{
public:
virtual void foo() override {CRTP<DD2>::foo_impl(*this);}
friend class CRTP<DD2>;
};
相关文章:
- 有没有比在库中添加一个并非由所有派生类实现的新虚拟函数更好的设计实践
- 检查一个类型是否直接派生自"enable if"上下文中的另一个类型(是其子类型)
- 给定一个类型,如何派生一个泛型更广泛的类型(例如,用于溢出安全求和)?
- C++重载函数,一个采用基类的参数,另一个采用派生类的参数
- C ++如何在原始抽象类中创建一个函数,该函数接受派生类的输入
- 如何将一个变量用于父类和派生类
- 两个抽象类,派生自同一个基类.如何访问从一个抽象类到另一个抽象类的指针
- 用于从一个基派生的类的GDB漂亮的打印机
- 存储在一个通用容器中的派生对象.如何避免铸造
- C++多态性:如何测试一个类是否派生自另一个基类
- 派生类不能用另一个基类的成员重载基类中的私有成员
- 通过 c++ 中的 udp 套接字将派生类对象从一个进程发送到另一个进程
- 是否可以在引用另一个派生类的派生类中声明复制构造函数?
- 如果我们有一个基*类,如何访问派生模板类的成员函数
- 无法从派生类型的作用域访问另一个实例的受保护成员
- C 有一个关键字,允许从派生类引用基本类型
- 从一个函数和某些类型指定符定义整个派生类的宏
- 是否有可能有一个派生类继承最终函数但创建相同的函数(而不是重写)
- 在C++中从模板类本身派生一个模板类
- 在c++中基于另一个变量类型派生一个变量类型