嵌套抽象基类的泛型模板

Generic template for nested abstract base classes

本文关键字:泛型 抽象 基类 嵌套      更新时间:2023-10-16

我正在尝试创建一个可用于模板其他类的类。也许我正在寻找错误的关键字。从本质上讲,我希望PrimaryClass和类A是纯虚拟的。DerivedClassC派生自它们各自的类。问题是,通过调用继承的类:CDerivedClass,我并没有覆盖纯虚拟PrimaryClass。我知道这一点,但我不知道如何解决它。

我的印象是,既然C是从A派生出来的,它就会起作用。 如果我更改C

virtual void DoFunThings ( C<T>* d ) {}

A它有效,但这样做的目的是允许使用不同派生版本的A

template <class T>
class A
{
public:  
virtual void FunThings ( const A<T> &orig, A<T>* new_one ) = 0;   
T thing{};
};

template <class T>
class C: public A < T >
{
public:
virtual void FunThings ( const C<T> &orig, C<T>* new_one ) {}
};

template <class T>
class PrimaryClass
{
public:    
virtual void DoFunThings ( A<T>* d ) = 0;
};

template<class T>
class DerivedClass: public PrimaryClass<T>
{
public:
virtual void DoFunThings ( C<T>* d ) {}
};

int main ()
{
DerivedClass<int> derived;
return 0;
}

如果不可能以这种方式做到这一点,那么如何使用我想要的功能制作通用的面向对象代码呢?

当然,您不会在DerivedClass中覆盖PrimaryClassDoFunThings。 你只是超载它。 要覆盖它,它们必须具有相同的签名。 您可以使用override关键字轻松地在 C++11 中检测到此错误。

template <class T>
class A
{
public:  
virtual void FunThings ( const A<T> &orig, A<T>* new_one ) = 0;   
T thing{};
};
template <class T>
class C: public A < T >
{
public:
virtual void FunThings ( const C<T> &orig, C<T>* new_one ) {}
};
template <class T>
class PrimaryClass
{
public:    
virtual void DoFunThings ( A<T>* d ) = 0;
};
template<class T>
class DerivedClass: public PrimaryClass<T>
{
public:
virtual void DoFunThings ( C<T>* d ) override {}
};
int main ()
{
DerivedClass<int> derived;
}

现在编译器(在我的例子中是 Clang)将发出一个错误:

test.cpp:27:18: error: 'DoFunThings' marked 'override' but does not override any
member functions
virtual void DoFunThings ( C<T>* d ) override {}

解决方案是给 PrimaryClass 和 DerivedClass 模板,而不是 A 和 C 的唯一数据类型(问题中的 int),而是为 A 和 C 类。

template <class D>
class PrimaryClass
{
public:
virtual void DoFunThings ( D* d ) = 0;
};

template<class D>
class DerivedClass: public PrimaryClass<D>
{
public:
virtual void DoFunThings ( D* d ) {}
};

int main ()
{
DerivedClass<C<int>> derived;
return 0;
}

我有一个错误的假设,即由于C是从A派生的,因此可以使用它。不知道我在哪里阅读/误解了它,但它导致浪费了很多时间。

您可以使用一些机器和模板来模拟虚拟函数模板,并获得非常接近您正在寻找的内容(可能)。
举个例子:

#include<type_traits>
#include<iostream>
template <class T>
class A {};
template <class T>
class B: public A < T > {};
template <class T>
class C: public A < T > {};
template <class>
class PrimaryClass;
template <typename T, template<typename> class U>
class PrimaryClass<U<T>>
{
template<typename D, typename Z = U<T>>
auto DoFunThings(int, D *d)
-> decltype(static_cast<Z*>(this)->DoFunThingsOverride(d)) {
return static_cast<Z*>(this)->DoFunThingsOverride(d);
}
void DoFunThings(char, A<T> *) {
// do whatever you want if
// derived class has not a
// proper specialization
std::cout << "PrimaryClass::DoFunThings" << std::endl;
}
public:
template<typename D>
std::enable_if_t<std::is_base_of<A<T>, D>::value, void>
DoFunThings ( D* d ) {
DoFunThings(0, d);
}
};
template<class T>
class DerivedClass: public PrimaryClass<DerivedClass<T>>
{
public:
void DoFunThingsOverride ( C<T>* ) {
std::cout << "DerivedClass::DoFunThings" << std::endl;
}
};

int main ()
{
DerivedClass<int> derived;
B<int> b;
C<int> c;
derived.DoFunThings(&b);
derived.DoFunThings(&c);
return 0;
}

在魔杖盒中看到它。