【发布时间】:2015-02-06 00:10:13
【问题描述】:
我正在开发一个使用 tcl 解释器的项目,我们将 c++ 对象和方法绑定到 tcl 命令。绑定是具有 ClientData 指针参数(几乎是 void*)的 c++ 函数。然后,我们将其转换为我们期望的对象,并与该对象进行交互。
我正在整合一组模板化的类。当我将这些类绑定到 tcl 命令时,我不知道模板参数,所以我使用抽象的“接口”基类与它们交互并将模板参数放在实现类中,所以我不需要模板参数使用它们。
最重要的是,我有一个处理所有常见操作的基类,以及处理所有其他事情的派生类,它们都有接口类。
我创建了一个简单的示例来说明我想要完成的工作。但是我的代码显然更复杂。
StackTest.h
#include <string>
#include <iostream>
#define STRLEN 1000
class BaseInterFace
{
public:
BaseInterFace(){};
virtual ~BaseInterFace(){};
virtual const char *GetNameOfClass() const=0;
virtual void BaseAction()=0;
};
template<typename T>
class Base: public BaseInterFace
{
public:
Base(){};
virtual ~Base(){};
virtual const char *GetNameOfClass() const
{
std::cout << "This is " << this << std::endl;
return "Base";
}
virtual void BaseAction(){
printf("Base Action Done.\n");
}
};
class DerivedInterface
{
public:
DerivedInterface(){};
virtual ~DerivedInterface(){};
virtual void DerivedAction(double value)=0;
};
template<typename T>
class Derived :
public Base<T>,public DerivedInterface
{
public:
char tclName_[STRLEN];
Derived(){};
virtual ~Derived(){};
virtual const char *GetNameOfClass() const
{ std::cout << "This is " << this << std::endl;
return "Derived";
}
virtual void DerivedAction(double value){
printf("Derived Action Done.\n");
}
};
简单示例 这个例子没有意义,因为我知道类型。但是当我不这样做时它会模拟,这就是我使用它的方式。
Derived <short> *a = new Derived <short>();
void *cd = (void *)a;
printf("Base_BaseActionMtd\n");
BaseInterFace *b = (BaseInterFace *)cd;
printf("InputClass: %s\n",b->GetNameOfClass());
b->BaseAction();
printf("Done!\n");
BaseInterFace *b2 = (BaseInterFace *)cd;
printf("InputClass: %s\n",b2->GetNameOfClass());
DerivedInterface *c = (DerivedInterface *)cd;
c->DerivedAction(.01);
printf("Done!\n");
这个输出:
Base_BaseActionMtd
This is 0x1089fdc00
InputClass: Derived
Base Action Done.
Done!
This is 0x1089fdc00
InputClass: Derived
This is 0x1089fdc00
Done!
派生动作没有发生,它调用GetNameOfClass?我不明白。即使我在派生接口中放了一个 printf,也不会出现。
此外,如果我在派生中切换继承顺序,我会从 BaseAction 得到奇怪的行为。
看起来我的 vtables 发生了一些奇怪的事情。这可能与模板参数有关吗?
如果我使用(Derived<short> *) 进行投射,它工作正常。
我想了解我做错了什么,以及如何正确地使用模板进行 MI。
据我所知,这些操作没有任何歧义。
所以我的问题是双重的。
1) MI 是这里的正确答案吗?有很多类需要派生,另一个继承链将使用相同的 Base,所以我想尽可能多地重用代码。但如果有更好的方法,我宁愿避免 MI。
2) 我对 MI 做错了什么?
【问题讨论】:
-
stackoverflow.com/help/mcve,此代码中有太多语法错误,无法从表面上理解(
template<T>、virtual DerivedAction()=0;Derived<short> a = new Derived<short>();等等等等)。 -
这太冗长了,不是最低限度的工作示例。您应该制作一个最小的工作示例并减少文本以说明您遇到的问题以及您遇到的问题。我不认为你会因此受到惩罚;但我确实认为人们会避免它,因为尝试解析它需要做很多工作。我知道我读完第一段就停止了阅读。
-
已编辑。抱歉,我复制粘贴了错误的 h 文件。我将它放入一个文件并删除了 tcl 代码。这种行为也发生在我的简单示例中。
-
你到底为什么要投给
BaseInterFace?它不是继承链的一部分,这只是未定义的行为。
标签: c++ templates inheritance multiple-inheritance