繁体   English   中英

用于继承的C ++模板参数问题

[英]Issues with C++ template arguments for inheritance

我对C ++模板有疑问。 更具体地说,通过使用模板参数进行继承。 在开放源代码的第三方库中,我面临着奇怪的行为。 有C方法

factoryReg(const char*, ICallback*)

它允许注册ICallback的子类并覆盖(简化的)方法:

class ICallback
{
public:
virtual void ENTRY(void* data) = 0;
virtual void EXIT(void* data) = 0;

const char* getName() { return _name; } const
ICallback(const char* name) : _name(name) {}
virtual ~ICallback() {}

private:
const char* _name;
};

我有

    class BaseCallback : public ICallback
    {
    public:
    BaseCallback(const char* name) : ICallback(name) {}
    virtual void ENTRY(void* data) { 
       std::cout << "in ENTRY base" << std::endl;
    }
    virtual void EXIT(void* data) { 
       std::cout << "in EXIT base" << std::endl;
    };

    class  SpecialCallback : public BaseCallback
    {
    public:
    SpecialCallback(const char* name) : BaseCallback(name) {}

    virtual void ENTRY(void* data) { 
    // actually, it's 3rd party code too - assumed to do something like
    ... 
    BaseCallback::ENTRY();
    }

    // no redecl. of EXIT(void* data)
    };

    template <typename Base>
    TemplCallback : public Base
    {
    public:
    TemplCallback(Base& myT) : Base(myT.getName()), _myT(myT)
    virtual void ENTRY(void* data) { 
       std::cout << "in ENTRY templ." << std::endl;
       _myT.ENTRY(); 
    }
    virtual void EXIT(void* data) {
       std::cout << "in EXIT templ." << std::endl;
       _myT.EXIT(); 
    }

    private:
       Base& _myT;
    }

注册后

SpecialCallback spc("validName");
TemplCallback<SpecialCallback> myCallback(spc);
factoryReg(spc.getName(), &myCallback);
...
// output: "in ENTRY base"
//         "in EXIT base" 

回调以某种方式不起作用(调试输出未输出//断点不适用)。

如果我在模板类TemplCallback中省略了EXIT(void * data)方法的实现,则一切正常!

// output: "in ENTRY templ."
//         "in EXIT base" 

这是预期的行为吗? 我被告知这可能是我使用的MSVC编译器13.10.6030的问题。 不确定。

顺便说一句:这里提出的模板想法可能不是我尝试做的任何事情的最佳选择;)但是,无论设计问题如何,我仍然对这件事本身感兴趣。

我怀疑factoryReg实际上并没有调用回调,而是存储了指针并在发生某些情况时调用了回调。

如果是这种情况,则此代码:

TemplCallback<SpecialCallback> myCallback(spc);
factoryReg(spc.getName(), &myCallback);

使factoryReg存储指向一个临时指针,该指针将在您的注册函数返回后立即超出范围。 因此,在调用回调时,该对象不是活动的,并且您具有未定义的行为。

您的TemplCallback类看起来很有趣。 我认为您实际上并不希望它使用其他对象,而是调用ENTRYEXIT的继承版本:

template <class Base>
class TemplCallback : public Base
{
public:
    TempCallback(const char* name) : Base(name)
    {}

    virtual ENTRY(void* data) 
    { 
       // do special processing

       Base::ENTRY(data); 
    }

    virtual EXIT(void* data)
    { 
       // do special processing

       Base::EXIT(data); 
    }
};

好的,可以肯定地假设SpecialCallback :: ENTRY()以某种方式调用BaseCallback :: EXIT()。 不能100%确定,因为它是封闭源代码-但很有可能。

“回调”功能就这么多...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM