我这里有一个名为base_class
的抽象基类,定义如下:
class base_class
{
public:
virtual ~base_class() = 0 {}
virtual size_t area() const = 0;
protected:
base_class() {}
};
来自它的一个派生类:
template <typename T> class A : public base_class
{
public:
A();
~A();
size_t area() const;
void display();
(...) etc code
};
另一个班级仍然来自它:
template <typename T> class B : public base_class
{
public:
B();
~B();
size_t area() const;
void set();
(...) etc code
};
比我有这个实例化和函数调用:
base_class *p = new A<int>;
p->display();
delete p;
p = new B<float>;
p->set();
(...) code
正如您可能已经观察到的那样,指针p
赢了&#34;&#34;&#34;&#34; display
和set
方法。
问题是:当使用base_class
类型的指针时,是否有可能让派生对象调用仅在其指向的类中定义的派生方法?因此能够访问显示和设置方法而不必在基类中使它们成为虚拟。
否则我们必须在base_class
,display
和set
中制作2个虚拟函数,这非常不方便,因为{{1不必继承A
方法,set
B
方法。
答案 0 :(得分:0)
如果无法确定对象的运行时类型,则可以使用dynamic_cast
向下转换从基类到派生类。
base_class *p = new A<int>;
if (A<int> *pa = dynamic_cast<A<int> *>(p))
pa->display();
delete p;
p = new B<float>;
if (B<float> *pb = dynamic_cast<B<float> *>(p))
pb->set();
如果在编译时可以确认对象的类型,static_cast
也可以执行转换,但要注意:您告诉编译器您知道的事实是指向的是什么类型。如果你错了,那么强制转换不能告诉你这个问题(就像dynamic_cast
一样,如果转换失败会返回一个空指针,或者为引用强制转换失败抛出std::bad_cast
),充其量,你会得到虚假的运行时错误和/或程序崩溃。
无论如何,最佳做法应该是重新安排继承关系,尝试使用虚函数,避免向下倾斜。
答案 1 :(得分:0)
我不太确定你最终想要做什么,但通常不好的做法是使用指向基类的指针从基类中不是虚拟的派生类调用函数。如前所述,您可以使用类型转换来实现此目的,但您需要在尝试调用函数之前检查dynamic_cast是否可行。
您是否考虑在基类中创建纯虚函数,例如:
public:
virtual void doIt() = 0;
然后你可以在派生类中实现它来调用你想要的函数:
class A
{
void doIt()
{
display();
}
};
class B
{
void doIt()
{
set();
}
};
答案 2 :(得分:0)
实际上没有办法访问成员,因为所有程序都知道它不必是派生类,并且可能只是基类。这意味着在评论中提到了。
指针只是一个整数,对于32位操作系统来说,它是一个32位的int,对于64位,我想你猜对了吗? 64位整数。
在键入指向实际类和结构等的指针时,由API来决定是否显示该函数,它更像是帮助者。
至于程序只知道它是基类指针,你只能访问它的变量。但是,如果你100%确定你正在处理什么,并且你想在这里保存性能,那就是伪代码。
typedef void (A::*func)(void*);
func f = &A::set;
base_classPointer->*f();
但是从一开始就要保持安全和声音,制作实际课程的指针,因为看起来你确定它实际上是一个A类。 或者使用动态,静态,强制转换。
if(B * b = static_cast or dynamic_cast<B*>(mypointer))
现在我建议你使用精确的指针类型,如果你完全确定它将会是什么。或者使用自己的演员阵容。如果您对性能非常担心,请尝试使用简单的委托方法。