类方法的PostActive可见性

PostActive visibility of class methods

本文关键字:可见性 PostActive 类方法      更新时间:2023-10-16

这里有一个抽象基类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不会"看到"displayset方法。



问题是:当使用base_class类型的指针时,是否有机会让派生对象调用仅在其指向的类中定义的派生方法?这样就可以访问display和set方法,而不必在基类中将它们设为虚值。

否则我们将不得不在base_class, displayset中创建2个虚函数,这非常不方便,因为A不必继承set方法,B不必继承display方法。

如果不能确定对象的运行时类型,可以使用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表示引用强制转换失败),并且,充其量,您将得到虚假的运行时错误和/或程序崩溃。

无论如何,最佳实践应该是重新安排继承关系,尽量使用虚函数,避免向下转换

我不太确定你最终想要做什么,但通常不是很好的做法,从派生类调用函数,在基类中使用指向基类的指针不是虚拟的。如前所述,您可以使用类型强制转换来实现这一点,但是您需要在尝试调用该函数之前检查dynamic_cast是否可行。

您是否考虑过在基类中创建一个纯虚函数,例如:
public:
  virtual void doIt() = 0;

然后你可以在派生类中实现它来调用你想要的函数:

class A
{
void doIt()
{
    display();
}
};
class B
{
void doIt()
{
    set();
}
};

实际上没有办法访问成员,因为程序知道它不一定是派生类,可以只是基类。这意味着在注释中提到的强制转换。

指针只是一个整数,对于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))

现在我建议你使用自己的精确指针类型,如果你完全确定它将是什么。或者使用你自己的模型。如果您确实对性能感到焦虑,可以尝试简单的委派方法。