1

这里的人们在该领域使用 C++ 抽象基类构造函数做什么?我说的是没有数据成员和非纯虚拟成员的纯接口类。

任何人都可以演示任何以有用的方式使用 ABC 构造函数的习语吗?或者仅仅是使用 ABC 实现接口的本质,它们保持为空、内联和受保护?

4

6 回答 6

5

任何人都可以演示任何以有用的方式使用 ABC 构造函数的习语吗?

这是一个例子,虽然这是一个人为的、不常见的例子。

您可以使用它来保存所有实例的列表:

class IFoo
{
private:
  //static members to keep a list of all constructed instances
  typedef std::set<IFoo*> Set;
  static Set s_set;

protected:
  //new instance being created
  IFoo()
  {
    s_set.insert(this);
  }

public:
  //instance being destroyed
  virtual ~IFoo()
  {
    s_set.remove(this);
  }

  ... plus some other static method and/or property
      which accesses the set of all instances ...
};

或者仅仅是使用 ABC 实现接口的本质,它们保持为空、内联和受保护?

更常见的是,它们根本没有被宣布!没有理由声明它们:

  • 空和内联 => 为什么要声明它?
  • Protected => ABC 可能已经有一些纯虚方法,因此除了作为子类之外已经无法实例化。
于 2009-01-17T17:00:54.247 回答
3

假设所有派生类都有一些共同的行为。例如在某个外部注册表中注册自己,或检查某事的有效性。

所有这些公共代码都可以放在基类的构造函数中,并且将从每个派生类的构造函数中隐式调用。

于 2009-01-17T16:46:02.730 回答
1

抽象基类的构造函数如何用于任何事情

假设您有一个抽象基类 B 和一个派生类 D。当创建 D 类型的对象时,首先调用 B 的构造函数,但此时对象“仍然”属于 B 类型(参见此处)——在特别是,从 B 的构造函数主体调用任何虚函数将调用B 自己的这些函数的实现。但是如果 B 是一个纯抽象类,这些虚函数都没有定义,所以程序会立即崩溃。

我猜你打算让 B 的构造函数调用虚函数的最派生类(例如 D 的)实现,对吗?这通常是一个坏主意,因为 D 的对象尚未完全构造,因此从 D 的虚函数实现内部对 D 中的成员变量的任何访问都将访问未初始化的内存。

于 2009-01-17T16:35:01.037 回答
1

记住:“资源获取就是初始化”

有时我们使用抽象基类作为某种锁定机制。例如,在多线程环境中,多个线程需要共享一个资源,那么一个线程可以使用构造函数作为获取资源的方式,使用析构函数来释放资源

void PlayWithPaintBallGun(Target &target)
{
    PaintBallGun paintBallGun;    // constructor waits until the gun is free,
                                  // then picks it up.

    paintBallGun.Aim(target);     // Shoot something
    paintBallGun.Fire();          //

                                  // Clever! The destructor is automatically
                                  // called when it goes out of scope. So we
                                  // can't forget to put the gun down.
}

雨果

于 2009-01-17T16:44:44.543 回答
1

我想不出很多有用的例子。没有数据成员的类没有状态,因此无法初始化任何东西。不过,您可以让构造函数/析构函数为您记录日志。例如,要记录所有访问者对象的创建/销毁:

class Visitor {
public:
    Visitor() {
        std::cout << "Visitor@" << this << " created" 
                  << std::endl;
    }

    virtual ~Visitor() {
        std::cout << "Visitor@" << this << " destroyed" 
                  << std::endl;
    }

    virtual void visitA(A*) = 0;
    virtual void visitB(B*) = 0;
    // ...
};
于 2009-01-17T20:39:23.853 回答
0

通常它只是将成员初始化为合理的值。

于 2009-01-17T15:16:09.900 回答