2011-11-06 17 views
4

假设我有两个继承具有纯虚函数的基类的类。这两个类都实现了它自己的那个函数版本,但不添加额外的成员变量,因此它们具有相同的大小。现在有时候,在程序执行过程中,我想将一个类转换为另一个类而不复制其所有数据。所以基本上我想让它使用其他类的虚拟表。有没有一种便携的方式来做到这一点?在运行时动态更改虚拟指针

回答

4

可移植的方法是实现你自己的类系统,它实际上具有可被复制的虚拟指针。

标准C++中没有这样的虚拟指针。

+0

能否请您就如何做到这一点的例子吗? – CODError

3

有没有一种便携的方式来做到这一点?

绝对不是。关于如何实现虚拟功能的具体细节并未由规范定义,因此不存在假装一个虚拟类别是另一种虚拟类别的方式。

4

没有。就语言而言,不存在虚拟表格之类的东西,更不用说关于它的外观/包含/存储位置的规则。

某种形式的作文可能更适合您的任务。

3

正如其他答案所说,实际上改变vtable是绝对不可移植的。

不过,也有一些变通办法,可以让你完成类似的语义没有实际改变类类型:

这种简单的解决办法是用描述当前实施的枚举“滚你自己的”遗产:

class MyClass 
{ 
    public: 
    enum DerivedType { A, B }; 

    private: 
    DerivedType myType; 

    public: 
    void myVirtualFunction() 
    { 
     if (myType == A) 
      myAFunction(); 
     else 
      myBFunction(); 
    } 
} 

您也可以使用函数指针作为公共成员变量,该变量设置为指示类类型的函数。然后你可以设置功能指针到另一个类的功能来“改变它的类型”

既然你提到你想避免复制数据,你可以保留你的不同的类,但有引用计数指针给你所有的成员变量,以便您可以快速创建彼此相反类型的新对象。

4

挪威安徒生咨询公司(现埃森哲)的一位年轻同事曾经向我提出过​​一个严重的问题。他们在Visual Basic中开发的应用程序花了很长时间来加载。他怀疑这可能是因为他们把每个类放在它自己的DLL中?

由于担心最坏情况,我进一步询问。是的,他们也有任何崩溃等问题

他怀疑,否则莫名其妙的崩溃可能会连接到他们的巧妙方案改变对象的类型在运行时,通过替换vtable指针?

我建议也许他们不应该做这些事情。他怀疑地看着我,冒险说他们没有时间再次从零开始做事。事实上,他们已经在扩展它,并且存在各种各样的问题,比如他们的项目负责人坚持他们在客户现场工作,而不是参加强制性会议。对我而言,这听起来像蘑菇管理(让他们在黑暗中,当一个人头弹出来,切开它):这些东西经常一起。

无论如何,我给你的建议是:不要。

或许可以改为实现快速移动操作,从移动数据b

或者,您可能会发现,这些都是不成熟的优化

干杯&心连心,

+0

我同意100%。好像开发已经够难了!当一些承包商决定增加一些额外的数据成员到'他们'的子类时会发生什么?我认为继承等的一个原因就是为了避免这类旅行。 –

0

即使这个问题是旧的,我想弹出一个办法做到这一点。 (对可移植性不太确定)

从我所了解的你有一个类BC继承自某个类A并且它们之间只存在一个虚函数。 (如果BC是不相关的,以及我在这里的方法工作。)

class A { 
public: 
    virtual std::string hello() = 0; 
}; 

class B : public A { 
public: 
    virtual std::string hello() { return "B"; } 
}; 

class C : public A { 
public: 
    virtual std::string hello() { return "C"; } 
}; 

然后你想利用BC然后调用hello,并得到"B"


所以,有一种方法来创建boost::any的淡化版本,只要它符合:)

struct parent {}; 

template< typename T > 
struct child : public parent { 
    child(T const& t): item(t){} 
    mutable T item; 
}; 

template< typename T > 
T& as(parent const & p) { return static_cast< child<T> const& >(p).item; } 

会投什么东西然后一切都混合在一起:

B b; 
parent* p = new child<B>(b); 
std::cout << as<C>(*p).hello() << std::endl; 
// ==== OUTPUT ==== 
// B 

可以看到代码在行动here


再向前迈进一步,我们可以创建一个从一种类型到另一种转换无需提供有关他们之间发生的事情一个蚊蚋的追尾功能。

template< typename TO, typename FROM > 
TO& convert(FROM const& from) { 
    parent* p = new child<FROM>(from); 
    return as<TO>(p); 
}; 

这可以运行here

(意识到我错过了这些示例代码链接的继承,但看完这个问题后,我认为这是实际需要的。所以,看到没有继承测试去here


一些其他代码,我开始玩,我认为可能会帮助一些以及...

#include <iostream> 
#include <string> 

class B { 
public: 
    virtual char hello() {return 'B';} 
}; 

class C { 
public: 
    virtual int hello() {return 65;} 
}; 

struct parent {}; 

template< typename T > 
struct child : public parent { 
    child(T const& t): item(t){} 
    mutable T item; 
}; 

template< typename T > 
T& as(parent const & p) { return static_cast< child<T> const& >(p).item; } 

template< typename TO, typename FROM > 
TO& convert(FROM const& from) { 
    parent* p = new child<FROM>(from); 
    return as<TO>(*p); 
}; 

int main() 
{ 
    B b; 
    std::cout << convert< C, B >(b).hello() << std::endl; 
    C c; 
    std::cout << convert< B, C >(c).hello() << std::endl; 
} 
// ==== OUTPUT ==== 
// 66 
// A 

想出如何使这一切的转换函数中:

template< typename TO, typename FROM > 
TO& convert(FROM const& from) { 
    struct parent {}; 

    struct child : public parent { 
     child(FROM const& t): item(t){} 
     mutable FROM item; 
    }; 

    struct sibling : public parent { 
     sibling(TO const& t): item(t){} 
     mutable TO item; 
    }; 

    parent* p = new child(from); 
    return static_cast< sibling const& >(*p).item; 
};