What do people here use C++ Abstract Base Class constructors for in the field? I am talking about pure interface classes having no data members and no non-pure virtual members.
人们在这里使用C ++抽象基类构造函数?我说的是没有数据成员且没有非纯虚拟成员的纯接口类。
Can anyone demonstrate any idioms which use ABC constructors in a useful way? Or is it just intrinsic to the nature of using ABCs to implement interfaces that they remain empty, inline and protected?
任何人都可以用有用的方式展示任何使用ABC构造函数的习语吗?或者它只是固有的使用ABCs实现接口,它们保持空,内联和保护?
6 个解决方案
#1
Can anyone demonstrate any idioms which use ABC constructors in a useful way?
任何人都可以用有用的方式展示任何使用ABC构造函数的习语吗?
Here's an example, although it's a contrived, uncommon example.
这是一个例子,虽然它是一个人为的,不常见的例子。
You might use it to keep a list of all instances:
您可以使用它来保留所有实例的列表:
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 ...
};
Or is it just intrinsic to the nature of using ABCs to implement interfaces that they remain empty, inline and protected?
或者它只是固有的使用ABCs实现接口,它们保持空,内联和保护?
More usually they're just not declared at all! There's no reason to declare them:
更常见的是,他们根本就没有宣布!没有理由声明它们:
- Empty and inline => why bother to declare it?
- Protected => the ABC probably already has some pure virtual methods and therefore already can't be instantiated except as a subclass.
空和内联=>为什么懒得申报呢?
Protected => ABC可能已经有一些纯虚方法,因此除了作为子类之外,已经无法实例化。
#2
Suppose that there is some behavior that is common for all the derived classes. Such as registering itself in some external registry, or checking validity of something.
假设存在一些对所有派生类都很常见的行为。比如在某些外部注册表中注册,或检查某些内容的有效性。
All this common code can be placed in base class's constructor, and it will be called implicitly from the constructors of each of the derived classes.
所有这些公共代码都可以放在基类的构造函数中,并且它将从每个派生类的构造函数中隐式调用。
#3
How could an abstract base class's constructor be used for anything?
如何将抽象基类的构造函数用于任何事情?
Suppose you have an abstract base class B and a derived class D. When an object of type D is created, B's constructor is called first, but at that point, the object "is" still of type B (see here) -- in particular, calling any virtual functions from the body of B's constructor will call B's own implementations of those functions. But if B is a pure abstract class, none of those virtual functions are defined, so the program will crash immediately.
假设你有一个抽象基类B和一个派生类D.当创建一个D类型的对象时,首先调用B的构造函数,但此时,对象“仍然”仍然是类型B(参见此处) - 在特别是,从B的构造函数的主体调用任何虚函数将调用B自己的那些函数的实现。但是如果B是纯抽象类,那么这些虚函数都没有定义,所以程序会立即崩溃。
I'm guessing that you intended for B's constructor to call down to the most-derived-class's (e.g. D's) implementation of a virtual function, right? That would be a bad idea in general because D's object is not fully constructed yet, so any accesses to member variables in D from inside D's implementation of the virtual function would access uninitialised memory.
我猜你打算让B的构造函数调用虚函数的最派生类(例如D')实现,对吧?这通常是一个坏主意,因为D的对象尚未完全构造,因此从D的虚函数实现中对D中的成员变量的任何访问都将访问未初始化的内存。
#4
Remember: "Resource acquisition is initialization".
请记住:“资源获取是初始化”。
Sometimes we use abstract base classes as some kind of locking mechanism. For example, in a multi-threaded environment, where several threads need to share a single resource, then a thread can use the constructor as a way to acquire the resource, and the destructor to release the resource
有时我们使用抽象基类作为某种锁定机制。例如,在多线程环境中,多个线程需要共享单个资源,然后线程可以使用构造函数作为获取资源的方法,并使用析构函数来释放资源
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
#5
I can't think of many useful examples. A class without data-members has no state and thus can't initialize anything. You can have the constructor/destructor do logging for you, though. For example, to log the creation/destruction of all Visitor objects:
我想不出很多有用的例子。没有数据成员的类没有状态,因此无法初始化任何内容。但是,您可以让构造函数/析构函数为您执行日志记录。例如,要记录所有Visitor对象的创建/销毁:
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;
// ...
};
#6
usually its solely to initialise members to sensible values.
通常只是将成员初始化为合理的价值观。
#1
Can anyone demonstrate any idioms which use ABC constructors in a useful way?
任何人都可以用有用的方式展示任何使用ABC构造函数的习语吗?
Here's an example, although it's a contrived, uncommon example.
这是一个例子,虽然它是一个人为的,不常见的例子。
You might use it to keep a list of all instances:
您可以使用它来保留所有实例的列表:
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 ...
};
Or is it just intrinsic to the nature of using ABCs to implement interfaces that they remain empty, inline and protected?
或者它只是固有的使用ABCs实现接口,它们保持空,内联和保护?
More usually they're just not declared at all! There's no reason to declare them:
更常见的是,他们根本就没有宣布!没有理由声明它们:
- Empty and inline => why bother to declare it?
- Protected => the ABC probably already has some pure virtual methods and therefore already can't be instantiated except as a subclass.
空和内联=>为什么懒得申报呢?
Protected => ABC可能已经有一些纯虚方法,因此除了作为子类之外,已经无法实例化。
#2
Suppose that there is some behavior that is common for all the derived classes. Such as registering itself in some external registry, or checking validity of something.
假设存在一些对所有派生类都很常见的行为。比如在某些外部注册表中注册,或检查某些内容的有效性。
All this common code can be placed in base class's constructor, and it will be called implicitly from the constructors of each of the derived classes.
所有这些公共代码都可以放在基类的构造函数中,并且它将从每个派生类的构造函数中隐式调用。
#3
How could an abstract base class's constructor be used for anything?
如何将抽象基类的构造函数用于任何事情?
Suppose you have an abstract base class B and a derived class D. When an object of type D is created, B's constructor is called first, but at that point, the object "is" still of type B (see here) -- in particular, calling any virtual functions from the body of B's constructor will call B's own implementations of those functions. But if B is a pure abstract class, none of those virtual functions are defined, so the program will crash immediately.
假设你有一个抽象基类B和一个派生类D.当创建一个D类型的对象时,首先调用B的构造函数,但此时,对象“仍然”仍然是类型B(参见此处) - 在特别是,从B的构造函数的主体调用任何虚函数将调用B自己的那些函数的实现。但是如果B是纯抽象类,那么这些虚函数都没有定义,所以程序会立即崩溃。
I'm guessing that you intended for B's constructor to call down to the most-derived-class's (e.g. D's) implementation of a virtual function, right? That would be a bad idea in general because D's object is not fully constructed yet, so any accesses to member variables in D from inside D's implementation of the virtual function would access uninitialised memory.
我猜你打算让B的构造函数调用虚函数的最派生类(例如D')实现,对吧?这通常是一个坏主意,因为D的对象尚未完全构造,因此从D的虚函数实现中对D中的成员变量的任何访问都将访问未初始化的内存。
#4
Remember: "Resource acquisition is initialization".
请记住:“资源获取是初始化”。
Sometimes we use abstract base classes as some kind of locking mechanism. For example, in a multi-threaded environment, where several threads need to share a single resource, then a thread can use the constructor as a way to acquire the resource, and the destructor to release the resource
有时我们使用抽象基类作为某种锁定机制。例如,在多线程环境中,多个线程需要共享单个资源,然后线程可以使用构造函数作为获取资源的方法,并使用析构函数来释放资源
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
#5
I can't think of many useful examples. A class without data-members has no state and thus can't initialize anything. You can have the constructor/destructor do logging for you, though. For example, to log the creation/destruction of all Visitor objects:
我想不出很多有用的例子。没有数据成员的类没有状态,因此无法初始化任何内容。但是,您可以让构造函数/析构函数为您执行日志记录。例如,要记录所有Visitor对象的创建/销毁:
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;
// ...
};
#6
usually its solely to initialise members to sensible values.
通常只是将成员初始化为合理的价值观。