gpt4 book ai didi

C++ 抽象一个模板化类型,保留 T(虚拟)

转载 作者:行者123 更新时间:2023-11-30 05:23:54 25 4
gpt4 key购买 nike

我已经编写了一组两个类来帮助实现多态性,更具体地说,在我们有一组指向我们存储派生类的基类的指针的情况下。

有两种实现方式,一种是当前使用的,一种是实验版本。当前的实现在运行时工作,有一个 Type 的静态实例每个类(class),跟踪它的 parent 和 child Type (s);一个Object class 用作所有其他类的基类(包括为 Type 检索创建必要的静态和虚拟方法的宏。

实验性实现(与此处相关的实现)由一个模板化的 Type<T> 组成。和 Object 的相同结构适应新Type<T> .新Type<T>使用 <type_traits>对于它的所有操作。

接下来是实验类的资源:

Type.h

#ifndef QUIDOR_EXPERIMENTAL_TYPE_H
#define QUIDOR_EXPERIMENTAL_TYPE_H


// std
#include <type_traits>


namespace quidor {
namespace experimental {

template<class T> class Type {
public:
typedef T class_type;

public:
template<class O> // is<O>
bool operator ==(const Type<O> &) const {
return std::is_same<class_type, O>();
}

// more operators like the previous one

Type() = default;
~Type() = default;
};

}
}


#endif //QUIDOR_EXPERIMENTAL_TYPE_H

一切正常,没有问题,当我们开始进入 Object 时问题出现了及其衍生品。

Object.h

#ifndef QUIDOR_EXPERIMENTAL_OBJECT_H
#define QUIDOR_EXPERIMENTAL_OBJECT_H


// quidor
#include "Type.h"


#define QuidorObjectMeta(class) \
public: \
static constexpr const char * className() { \
return #class; \
} \
\
static const quidor::experimental::Type<class> classType() { \
return quidor::experimental::Type<class>(); \
} \
\
virtual const quidor::experimental::Type<class> getClassType() const { \
return class::classType(); \
} \
private:
//\ObjectMeta(class)


namespace quidor {
namespace experimental {

class Object {
public:
static const Type<Object> classType() {
return Type<Object>();
}

virtual const Type<Object> getClassType() const {
return Object::classType();
}

Object() = default;
virtual ~Object() = default;

private:
};

}
}

#endif //QUIDOR_EXPERIMENTAL_OBJECT_H

问题出在一个函数上:

virtual const Type<Object> getClassType() const

派生类,Derived , 会将此虚拟方法定义为(在 ObjectMeta 之后):

virtual const Type<Derived> getClassType() const

现在这显然是不合法的,因为 getClassType() 的返回类型不能改变它在 Object 中声明的内容.

该虚拟方法的存在是必需的,因为它表示我们如何从例如 Object * 类型的变量中获取实例的真实类型,这是所需的功能:

#include <quidor/experimental/Object.h>
#include <cassert>

class Derived : public quidor::experimental::Object {
QuidorObjectMeta(::Derived, quidor::experimental::Object);

Derived() = default;
virtual ~Derived() = default;
};

int main(int argc, char ** argv) {
using quidor::experimental;

Object * o = new Derived();

assert(o->getClassType() == Derived::classType()); // true

delete o;
return 0;
}

我“找到”的唯一解决方案是为 Type<T> 创建一个非模板化基类并返回它,当这个基类不知道 T 时,问题就出现了它的基础 Type<T> ;这个基类也不能有虚方法,因为这个方法必须模板化才能接收其他类型(O 的代码中的 Type<T>),模板化的虚方法是不合法的。

所以我来这里是为了寻求这个问题的解决方案,如果有的话,如果没有,为什么以及如何解决这个问题。提前谢谢你。

最佳答案

您似乎在尝试构建与 Smalltalk 层次结构非常相似的东西,其中每个类都有一个元类(它本身就是一个对象,即类的一个实例)。

在 Smalltalk 中,这是用这样的结构处理的1:

enter image description here

在此,实线表示继承,虚线表示实例(即,A - - -> B 表示 A 是 B 的实例)。灰线在普通类层次结构中,黑线在元类层次结构中2

其中一些可能难以在 C++ 中建模,尤其是元类和元类类之间的关系,其中元类的元类本身就是元类的一个实例。

我不确定这些细节是否足以准确地为系统建模;如果没有,您可能想花些时间阅读我在脚注 1 中引用的那本书。


  1. 虽然我重新绘制了它,但它本质上是 Smalltalk-80:语言及其实现 中图 16.5 的拷贝。
  2. 我意识到这个符号有点不寻常——但它是原来使用的,我试图合理准确地保留它。

关于C++ 抽象一个模板化类型,保留 T(虚拟),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38963074/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com