这里的人们在该领域使用 C++ 抽象基类构造函数做什么?我说的是没有数据成员和非纯虚拟成员的纯接口类。
任何人都可以演示任何以有用的方式使用 ABC 构造函数的习语吗?或者仅仅是使用 ABC 实现接口的本质,它们保持为空、内联和受保护?
这里的人们在该领域使用 C++ 抽象基类构造函数做什么?我说的是没有数据成员和非纯虚拟成员的纯接口类。
任何人都可以演示任何以有用的方式使用 ABC 构造函数的习语吗?或者仅仅是使用 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 实现接口的本质,它们保持为空、内联和受保护?
更常见的是,它们根本没有被宣布!没有理由声明它们:
假设所有派生类都有一些共同的行为。例如在某个外部注册表中注册自己,或检查某事的有效性。
所有这些公共代码都可以放在基类的构造函数中,并且将从每个派生类的构造函数中隐式调用。
抽象基类的构造函数如何用于任何事情?
假设您有一个抽象基类 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.
}
雨果
我想不出很多有用的例子。没有数据成员的类没有状态,因此无法初始化任何东西。不过,您可以让构造函数/析构函数为您记录日志。例如,要记录所有访问者对象的创建/销毁:
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;
// ...
};
通常它只是将成员初始化为合理的值。