你使用C++的ABC构造函数做什么? 为什么要声明它呢? Protected=>ABC可能已经有一些纯虚拟方法,因此除了作为子类之外,已经无法实例化。

你使用C++的ABC构造函数做什么? 为什么要声明它呢? Protected=>ABC可能已经有一些纯虚拟方法,因此除了作为子类之外,已经无法实例化。,c++,constructor,interface-design,abc,C++,Constructor,Interface Design,Abc,有人能用一种有用的方式演示使用ABC构造函数的习惯用法吗?或者,使用ABC实现接口的本质是保持空、内联和受保护吗?通常只将成员初始化为合理值。通常只将成员初始化为合理值。抽象基类的构造函数怎么能用于任何事情 假设您有一个抽象基类B和一个派生类D。当创建类型为D的对象时,会首先调用B的构造函数,但此时,该对象仍然是类型为B的请参见-特别是,从B的构造函数体调用任何虚拟函数都会调用B自己对这些函数的实现。但是如果B是一个纯抽象类,那么这些虚函数都没有定义,因此程序将立即崩溃 我猜你是想让B的构造函数

有人能用一种有用的方式演示使用ABC构造函数的习惯用法吗?或者,使用ABC实现接口的本质是保持空、内联和受保护吗?

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

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

抽象基类的构造函数怎么能用于任何事情

假设您有一个抽象基类B和一个派生类D。当创建类型为D的对象时,会首先调用B的构造函数,但此时,该对象仍然是类型为B的请参见-特别是,从B的构造函数体调用任何虚拟函数都会调用B自己对这些函数的实现。但是如果B是一个纯抽象类,那么这些虚函数都没有定义,因此程序将立即崩溃


我猜你是想让B的构造函数调用最派生的类,比如D的虚函数实现,对吧?一般来说,这是个坏主意,因为D的对象还没有完全构造好,所以从虚拟函数的D实现内部访问D中的成员变量都会访问未初始化的内存。

抽象基类的构造函数怎么能用于任何事情

假设您有一个抽象基类B和一个派生类D。当创建类型为D的对象时,会首先调用B的构造函数,但此时,该对象仍然是类型为B的请参见-特别是,从B的构造函数体调用任何虚拟函数都会调用B自己对这些函数的实现。但是如果B是一个纯抽象类,那么这些虚函数都没有定义,因此程序将立即崩溃


我猜你是想让B的构造函数调用最派生的类,比如D的虚函数实现,对吧?一般来说,这不是一个好主意,因为D的对象还没有完全构造好,所以从虚拟函数的D实现内部访问D中的成员变量都会访问未初始化的内存。

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

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

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.
}
Hugo

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

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

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.
}

Hugo

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


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

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

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

有人能用一种有用的方式演示使用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实现接口的本质是保持空的、内联的和受保护的吗

更常见的是,它们根本就没有申报!没有理由宣布:

Empty and inline=>为什么要声明它呢? Protected=>ABC可能已经有一些纯虚拟方法,因此除了作为子类之外,已经无法实例化。 有人能用一种有用的方式演示使用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实现接口的本质是保持空的、内联的和受保护的吗

更常见的是,它们根本就没有申报!没有理由宣布:

Empty and inline=>为什么要声明它呢? Protected=>ABC可能已经有一些纯虚拟方法,因此除了作为子类之外,已经无法实例化。 我不能 我想不出许多有用的例子。没有数据成员的类没有状态,因此无法初始化任何内容。不过,您可以让构造函数/析构函数为您做日志记录。例如,要记录所有访问者对象的创建/销毁,请执行以下操作:

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;
    // ...
};

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

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;
    // ...
};

有时候ABC真的有一个可以初始化的变量。有时候ABC真的有一个可以初始化的变量。我猜你是想让B的构造函数调用最派生的类,比如D的虚函数实现,对吗?不,我知道你不能这么做,也许应该在我的帖子里写上。安德鲁:那么你是说那些用静态成员做事情的CTOR,比如ChrisW的例子?由于您明确表示没有数据成员和非纯虚拟成员,您的选择非常有限……我猜您打算让B的构造函数调用最派生的类,例如D的虚拟函数实现,对吗?不,我知道你不能这么做,也许应该在我的帖子里写上。安德鲁:那么你是说那些用静态成员做事情的CTOR,比如ChrisW的例子?因为您明确表示没有数据成员和非纯虚拟成员,所以您的选择非常有限……这并不能真正回答我的问题。RAII类本身不是ABC,尽管它们可以使用它们。这并不能真正回答我的问题。RAII类本身不是ABC,尽管它们可以使用它们。你的例子基本上就是我所想的。我想到的另一个想法是利用构造顺序,以便能够安全地从继承权的较低层调用一些兄弟姐妹或成员,但我真的想不出这有什么用。你的例子基本上就是我所想的。我想到的另一个想法是利用构造顺序,以便能够安全地从继承权的较低层调用一些兄弟姐妹或成员,但我真的想不出这有什么用处。