C++ 抽象一个模板化类型,保留 T(虚拟)
C++ Abstract a templated type, keep T (virtual)
我写了一组两个 classes 来帮助实现多态性,更具体地说,在我们有一组指向基 class 的指针的情况下,我们在其中存储派生 classes.
有两种实现方式,一种是当前使用的,另一种是实验版本。当前的实现在运行时工作,每个 class 有一个 Type
的静态实例,它跟踪它的父子 Type
(s); Object
class 用作所有其他 class 的基础 class (包括为 Type
创建必要的静态和虚拟方法的宏检索。
实验性实施(与此处相关的实施)由模板化 Type<T>
和适用于新 Type<T>
的 Object
相同结构组成。新的 Type<T>
使用 <type_traits>
进行所有操作。
接下来是实验性 classes 的来源:
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
派生的 class、Derived
会将此虚拟方法定义为(在 ObjectMeta
之后):
virtual const Type<Derived> getClassType() const
现在这显然是不合法的,因为 getClassType()
的 return 类型不能改变它在 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;
}
我唯一的解决方案 "found" 是为 Type<T>
和 return 创建一个非模板化的基础 class ,相反,问题出现在这个基础上class 无法知道其基础 Type<T>
的 T
;这个基础 class 也不能有虚方法,因为这个方法必须模板化才能接收其他类型(Type<T>
代码中的 O
),而模板化的虚方法没有合法。
所以我来这里是为了寻求解决这个问题的方法,如果有的话,如果没有,为什么以及如何解决这个问题。提前谢谢你。
您似乎在尝试构建与 Smalltalk 层次结构非常相似的东西,其中每个 class 都有一个 metaclass (它本身就是一个对象 - 即 class).
在 Smalltalk 中,这是用这样的结构处理的1:
其中,实线表示继承,虚线表示实例(即,A - - -> B 表示 A 是 B 的实例)。灰线在正常 class 层次结构中,黑线在 metaclass 层次结构中2.
其中一些可能难以在 C++ 中建模,尤其是 Metaclass 和 Metaclass class 之间的关系,其中 Metaclass 的 Metaclass 本身就是 Metaclass.
的一个实例
我不确定这些细节是否足以准确地为系统建模;如果没有,您可能想花些时间阅读我在脚注 1 中引用的那本书。
- 虽然我重画了它,但它本质上是 Smalltalk-80: The Language and its Implementation.
中图 16.5 的副本
- 我意识到这个符号有点不寻常——但它是原来使用的,我试图合理准确地保留它。
我写了一组两个 classes 来帮助实现多态性,更具体地说,在我们有一组指向基 class 的指针的情况下,我们在其中存储派生 classes.
有两种实现方式,一种是当前使用的,另一种是实验版本。当前的实现在运行时工作,每个 class 有一个 Type
的静态实例,它跟踪它的父子 Type
(s); Object
class 用作所有其他 class 的基础 class (包括为 Type
创建必要的静态和虚拟方法的宏检索。
实验性实施(与此处相关的实施)由模板化 Type<T>
和适用于新 Type<T>
的 Object
相同结构组成。新的 Type<T>
使用 <type_traits>
进行所有操作。
接下来是实验性 classes 的来源:
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
派生的 class、Derived
会将此虚拟方法定义为(在 ObjectMeta
之后):
virtual const Type<Derived> getClassType() const
现在这显然是不合法的,因为 getClassType()
的 return 类型不能改变它在 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;
}
我唯一的解决方案 "found" 是为 Type<T>
和 return 创建一个非模板化的基础 class ,相反,问题出现在这个基础上class 无法知道其基础 Type<T>
的 T
;这个基础 class 也不能有虚方法,因为这个方法必须模板化才能接收其他类型(Type<T>
代码中的 O
),而模板化的虚方法没有合法。
所以我来这里是为了寻求解决这个问题的方法,如果有的话,如果没有,为什么以及如何解决这个问题。提前谢谢你。
您似乎在尝试构建与 Smalltalk 层次结构非常相似的东西,其中每个 class 都有一个 metaclass (它本身就是一个对象 - 即 class).
在 Smalltalk 中,这是用这样的结构处理的1:
其中,实线表示继承,虚线表示实例(即,A - - -> B 表示 A 是 B 的实例)。灰线在正常 class 层次结构中,黑线在 metaclass 层次结构中2.
其中一些可能难以在 C++ 中建模,尤其是 Metaclass 和 Metaclass class 之间的关系,其中 Metaclass 的 Metaclass 本身就是 Metaclass.
的一个实例我不确定这些细节是否足以准确地为系统建模;如果没有,您可能想花些时间阅读我在脚注 1 中引用的那本书。
- 虽然我重画了它,但它本质上是 Smalltalk-80: The Language and its Implementation. 中图 16.5 的副本
- 我意识到这个符号有点不寻常——但它是原来使用的,我试图合理准确地保留它。