То, что должно показаться простым, стало для меня настоящим камнем преткновения. У меня есть простое наследование, но я хочу, чтобы убедиться, что по крайней мере один экземпляр базового класса существует до построения любого из его производных типов:Убедитесь, что существует хотя бы один экземпляр базы до создания производного типа.
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
.
EDIT - Подумав об отношениях, что мне нужно между Parent
и Child
классом, я думаю, что я пришел к выводу, что было бы лучше, чтобы иметь еще один класс, который будет Abstract Base Class
что и Parent
и Child
типы наследуют независимо друг от друга. Таким образом, мой Manager
или Storage
класс, который имеет контейнер из них будет принимать shared_ptr<base_class>
так, что он может контейнер любого типа, то эти наследственные классы Parent
& Child
может содержать список references to pointers
из тех, что они связаны. Тогда будет отвечать классили Storage
, чтобы проверить, действительно ли самая первая запись в его контейнере является типом Parent
, а не Child
. Я пошел вперед и добавил это к первоначальному вопросу о будущих ссылках на другие. Мне все равно хотелось бы вернуться к приведенной выше конструкции, о которой я только что упомянул.
Возможно, вам понадобится статический член. –
Это похоже на [XY Problem] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) для меня, что вы на самом деле пытаетесь решить? – Rakete1111
Если вы меняете конструктор 'Child', требуется ссылка на' Parent', вы можете быть уверены, что существует 'Parent' –