这个问题已经在这里有了答案:
已关闭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 );