这个问题已经在这里有了答案:




已关闭8年。






如果我有一个抽象基类和一个从其派生的具体模板化类,而该类具有使用指向该基类的指针的方法,则该派生类似乎不再将自身视为从该派生类:

class AbstractBase
{
protected:
    virtual void test() = 0;
};

template < class T >
class Derived : public AbstractBase
{
public:
    virtual void call( AbstractBase* d ) { d->test(); }  //  Error!
protected:
    virtual void test() {}
};

int main()
{
    Derived< int > a;
    Derived< int > b;

    b.call( &a );

    return EXIT_SUCCESS;
}

出现以下错误:



编译器没错,绝对是protected-但是,如果Derived< T >继承自AbstractBase,为什么会抱怨呢?

最佳答案

不允许的原因是因为AbstractBase作为一种类型声明test protected 。除非当前类是AbstractBase的直接后代,否则这将使其对所有人都是私有(private)的。即使这样,该类也只能通过相同类的对象访问成员,而不是不同的后代,并且不能直接从AbstractBase本身访问成员。

template < class T >
class Derived : public AbstractBase
{
public:
    virtual void call( Derived * d ) {
        d->test(); // ok, d has same type as this
        AbstractBase *b = this;
        b->test(); // not ok
    }
protected:
    virtual void test() {}
};

如上所述,您可以只允许使用相同类型的指针。另外,您可以为Derived创建一个代理基类,以实现virtual方法来调用test。这将允许从不同的Derived类型进行访问。
class DerivedBase : public virtual AbstractBase
{
public:
    virtual void call( DerivedBase * d ) { d->test(); }
};

template < class T >
class Derived : public DerivedBase
{
protected:
    virtual void test() {}
};

可以这样访问:
   Derived< int > a;
   Derived< int > b;
   Derived< float > c;

   b.call( &a );
   c.call( &a );

07-28 00:42