看起来很简单的东西一直是我目前的绊脚石。我有简单的继承,但我想确保在构造任何派生类型之前至少存在一个基类实例:
class Parent {
private:
std::string name_;
explicit Parent( const std::string& name );
protected:
// Constructor that Derived Types Will Use
Parent( const std::string& parentName, const std::string& childName, bool isChildAParent = false );
};
Child : public Parent {
public:
Child( const std::string& parentName, const std::string& childName, bool isChildAParent = false );
};
// It is here in the 2nd or protected constructor that I'm struggling with.
Parent::Parent( const std::string& parentName, const std::string& childName, bool isChildAParent ) {
// How To Go about to check if an instance of Parent already exists that
// used its default constructor before using this constructor from a derived type?
}
主要用法是这样的:
int main() {
Child child( "parent", "child", false ); // Invalid since Parent wasn't created first
Parent parent( "parent" );
Child child( "parent", "child", false ); // Okay since parent exists.
return 0;
}
修改 - 基于来自Kerrek SB
的评论
我可能需要一个静态成员
这就是我现在所做的,而且我得到了我期待的行为。
·H
class Parent {
private:
std::string myName_; // Name of this parent
static bool isConstructed_;
bool isParent_;
protected:
std::string parentName_;
public:
// This must be called first at least once before trying to create any children classes.
// The importances of this dependence has to do with the pointer of this parent being stored
// in a vector (outside of this class), and every child created after this will create a family that belongs to this parent.
explicit Parent( const std::string& name );
Parent( Parent &&self );
Parent& operator=( Parent &&transfer );
Parent( Parent const & ) = delete;
Parent& operator=( Parent const & ) = delete;
//*virtual*/ void print() { }
virtual void printName() const;
virtual void printParentName() const;
const std::string& getName() const;
const std::string& getParentName() const;
protected:
// Constructor that is used when using inheritance.
explicit Parent( const std::string& parentName, const std::string& childName, bool isChildAParent = false );
};
class Child : public Parent {
public:
Child( const std::string& parentName, const std::string& childName, bool isChildAParent = false );
};
的.cpp
bool Parent::isConstructed_ = false;
// Initial Constructor Must Be Called First At Least Once.
Parent::Parent( const std::string& parentName ) :
myName_( parentName ) {
isConstructed_ = true;
isParent_ = true;
}
// Protected Constructor Used By Child Classes.
Parent::Parent( const std::string& parentName, const std::string& childName, bool isChildAParent ) {
// First check to see if this child will be a parent itself
if ( !isConstructed_ ) {
std::cout << "There must be at least 1 instance of a Parent\n"
<< "before constructing a child.\n";
} else {
myName_ = childName;
parentName_ = parentName;
isParent_ = isChildAParent;
}
}
// Move Constructor
Parent::Parent( Parent&& self ) {
}
// Move Opeartor
Parent& Parent::operator=( Parent&& self ) {
if ( this != &self ) {
}
return *this;
}
void Parent::printName() const {
std::cout << myName_ << std::endl;
}
void Parent::printParentName() const {
std::cout << parentName_ << std::endl;
}
const std::string& Parent::getName() const {
return myName_;
}
const std::string& Parent::getParentName() const {
return parentName_;
}
Child::Child( const std::string& parentName, const std::string& childName, bool isChildAParent ) :
Parent( parentName, childName, isChildAParent ) {
}
main.cpp - 第一个版本
int main() {
Parent p( "someParent" );
Child c( "someParent", "someChild" );
// Child's Construction is successful because Parent p exists
return 0;
}
main.cpp - 第2版
int main() {
Child c( "someParent", "someChild" );
// Still compiles and prints out the message that a parent needs to exists first
// This can be thrown as an exception to prevent the creation
// of a derived type without at least having a base type that already exists.
return 0;
}
谢谢Kerrek SB
。
编辑 - 在考虑了Parent
和Child
课程之间我需要的关系之后,我想我已经得出结论,可能会更好有另一个类Abstract Base Class
,Parent
和Child
类型将彼此独立地继承。这样,具有这些容器的Manager
或Storage
类将接受shared_ptr<base_class>
,以便它可以容纳任何类型,然后这些继承的类Parent
&amp; Child
可以包含与其关联的references to pointers
个列表。然后由Manager
或Storage
类负责检查其容器中的第一个条目实际上是Parent
类型而不是Child
类类型。我继续将此添加到原始问题中,以便将来引用其他人。我仍然希望能够反馈我刚刚提到的上述结构。
答案 0 :(得分:0)
为基类Parent提供一个静态整数对象,该对象在其构造函数中递增:
class Parent{
public:
Parent(){instances++;}
~Parent(){instances--;}
unsigned int instances(){return instances;}
private:
static unsigned int instances = 0;
然后,如果instances = 0:
,则在Child类中抛出异常class Child : public Parent{
public:
Child(){if(Parent::instances() == 0){throw "message"};
根据this wiki entry,在课程中使用throw
&#39;构造函数是阻止对象实例化的标准方法,包括堆栈和堆分配。 static
中的Parent
成员对象仅用于保持实例总数的运行记录。