基础 class 需要引用尚未构造的派生 class 成员
Base class needs reference to derived class member not yet constructed
有没有办法确保派生class创建的对象通过引用传递给基class已经构造并且仍然具有继承?
这是问题的基础:
class ClassA : public ClassA_Base {
public:
ClassA(int maxSize = 4000)
: ClassA_Base(xClassB_Object),
xClassB_Object(maxSize) {};
private:
ClassB xClassB_Object;
};
这是我能找到的最接近的答案。但他们并没有尝试使用继承:
how to prevent usage of class members not yet constructed?
编辑 1: 我实施了 Sam Varshavchik 的解决方案。
class ClassA : private ClassB, public ClassA_Base {
public:
ClassA(int maxSize = 4000)
: ClassB{maxSize},
ClassA_Base{static_cast<ClassB &>(*this)} {}
};
显然,我使用的函数名称与所讨论的示例代码不同,AppLevel、derived 和 base 的所有级别都包含更多代码。我的代码现在直接访问基本函数,而不是通过 xClassB_Object,所以我丢失了 "qualifier"。 "Where did that function come from that has little to do the the AppLevel/ClassA functionality?!"
为了减轻 "ambiguity",我在通话中使用了更多的限定条件。
而不仅仅是:
ClassB_Action()
查看完全合格的调用:
this->ClassB_Base::ClassB_Action()
我删除 "this->" 并使用以下内容:
ClassB_Base::ClassB_Action()
/编辑 1:
这里是问题的更详细的版本。
我有一串 classes。有些是工人,有些是为工人分配的。这为使用 classes.
提供了最大的灵活性
我的意图是让用户从链中的任何级别派生,而无需实现任何东西来支持基础 class,除了调用构造函数。然后直接使用基class的成员函数
问题是由于调用构造函数的顺序,当我的对象的引用传递给基础 class 的构造函数时,我的对象没有完全构造。我知道此时我可以传递引用,但我不能在基础 class 构造函数中使用它。
这是 classes 的整个链:
ClassB - moves data into memory (does not need ClassA)
ClassA - modifies the data and passes to ClassB
ClassB_Base - Worker (Operates on buffer)
ClassB - Allocator (Creates a buffer)
ClassA_Base - Worker (Operates on data and calls ClassB worker)
ClassA - Allocator (Creates a ClassB)
AppLevelClass - Top layer passing in data
//// ClassB_Base acts on the data
class ClassB_Base {
public:
ClassB_Base(int* pData, int* pIndex, int length)
: xpData(pData),
xpIndex(pIndex),
xLength(length) {}
void ClassB_Action(int* data) {
//// Do ClassB_Action stuff with the data
xpData = xpIndex = &xLength; // Junk code to eliminate compiler warning
}
private:
int* xpData;
int* xpIndex;
int xLength;
};
//// ClassB only allocates a data buffer for use in ClassB_Base
class ClassB : public ClassB_Base
{
public:
ClassB(int maxSize)
: ClassB_Base(new int[maxSize], &xIndex, maxSize) {}
private:
int xIndex;
};
//// ClassA_Base acts on the data and calls ClassB
class ClassA_Base {
public:
ClassA_Base(ClassB_Base& ClassB_Passed_Ref)
: xClassB_Object_Ref(ClassB_Passed_Ref) {}
void ClassA_Action(int *data) {
//// Do some ClassA_Action stuff with the data like sort or filter
xClassB_Object_Ref.ClassB_Action(data);
}
private:
ClassB_Base& xClassB_Object_Ref;
};
//// ClassA only instantiates a class for use in ClassA_Base
class ClassA : public ClassA_Base {
public:
ClassA(int maxSize = 4000)
: ClassA_Base(xClassB_Object),
xClassB_Object(maxSize) {}
private:
ClassB xClassB_Object;
};
用例:
//// Now using the whole chain
class AppLevelClass1 : public ClassA {
public:
AppLevelClass1(void) {
ClassA_Action(xData);
}
int xData[10];
};
//// Or using part of the chain
class AppLevelClass2 : public ClassB {
public:
AppLevelClass2(void) {
ClassB_Action(xData);
}
int xData[10];
};
//// Or using another part of the chain
class AppLevelClass3 : public ClassB_Base {
public:
AppLevelClass3(void) : ClassB_Base(xBuff, &xIndex, 100) {
ClassB_Action(xData);
}
int xData[10];
int xIndex;
int xBuff[1000];
};
//// Other use cases
int main() {
int data[10];
int index;
AppLevelClass myAppLevelClass;
myAppLevelClass.ClassA_Action(data);
ClassB_Base xClassB_Base(data, &index, 5);
xClassB_Base.ClassB_Action(data);
ClassB xClassB(1000);
xClassB.ClassB_Action(data);
ClassA_Base xClassA_Base1(xClassB_Base);
xClassA_Base1.ClassA_Action(data);
ClassA_Base xClassA_Base(xClassB);
xClassA_Base.ClassA_Action(data);
ClassA xClassA(1000);
xClassA.ClassA_Action(data);
}
在 C++ 中,基 class 总是在派生 class 的任何部分构造之前构造。没有例外,没有解决方法,没有替代方案。在基础 class 及其构造函数(如果有)returns 完全构建之前,派生 class 的任何部分都不存在。这是基础 C++。
不过
C++ 的另一个基本部分是多重继承,通过多重继承,所有基 classes 总是按声明顺序构造(我忽略了虚拟继承,这增加了一些与此处无关的额外复杂性) .
这几乎是您可以用来调整构建顺序的唯一工具。但这可以为您的优势谨慎使用。例如,而不是第一个示例中显示的代码:
class ClassA : private ClassB, public ClassA_Base {
public:
ClassA(int maxSize = 4000)
: ClassB{maxSize},
ClassA_Base{static_cast<ClassB &>(*this)}
{
}
};
不是让 ClassB
成为 ClassA
的私有成员,而是从它私有继承;然后将对它的引用传递给 ClassA_Base
的构造函数。 ClassB
首先得到完全构造,然后 ClassA_Base
得到对它的引用。
有没有办法确保派生class创建的对象通过引用传递给基class已经构造并且仍然具有继承?
这是问题的基础:
class ClassA : public ClassA_Base {
public:
ClassA(int maxSize = 4000)
: ClassA_Base(xClassB_Object),
xClassB_Object(maxSize) {};
private:
ClassB xClassB_Object;
};
这是我能找到的最接近的答案。但他们并没有尝试使用继承: how to prevent usage of class members not yet constructed?
编辑 1: 我实施了 Sam Varshavchik 的解决方案。
class ClassA : private ClassB, public ClassA_Base {
public:
ClassA(int maxSize = 4000)
: ClassB{maxSize},
ClassA_Base{static_cast<ClassB &>(*this)} {}
};
显然,我使用的函数名称与所讨论的示例代码不同,AppLevel、derived 和 base 的所有级别都包含更多代码。我的代码现在直接访问基本函数,而不是通过 xClassB_Object,所以我丢失了 "qualifier"。 "Where did that function come from that has little to do the the AppLevel/ClassA functionality?!"
为了减轻 "ambiguity",我在通话中使用了更多的限定条件。 而不仅仅是:
ClassB_Action()
查看完全合格的调用:
this->ClassB_Base::ClassB_Action()
我删除 "this->" 并使用以下内容:
ClassB_Base::ClassB_Action()
/编辑 1:
这里是问题的更详细的版本。
我有一串 classes。有些是工人,有些是为工人分配的。这为使用 classes.
提供了最大的灵活性我的意图是让用户从链中的任何级别派生,而无需实现任何东西来支持基础 class,除了调用构造函数。然后直接使用基class的成员函数
问题是由于调用构造函数的顺序,当我的对象的引用传递给基础 class 的构造函数时,我的对象没有完全构造。我知道此时我可以传递引用,但我不能在基础 class 构造函数中使用它。
这是 classes 的整个链:
ClassB - moves data into memory (does not need ClassA)
ClassA - modifies the data and passes to ClassB
ClassB_Base - Worker (Operates on buffer)
ClassB - Allocator (Creates a buffer)
ClassA_Base - Worker (Operates on data and calls ClassB worker)
ClassA - Allocator (Creates a ClassB)
AppLevelClass - Top layer passing in data
//// ClassB_Base acts on the data
class ClassB_Base {
public:
ClassB_Base(int* pData, int* pIndex, int length)
: xpData(pData),
xpIndex(pIndex),
xLength(length) {}
void ClassB_Action(int* data) {
//// Do ClassB_Action stuff with the data
xpData = xpIndex = &xLength; // Junk code to eliminate compiler warning
}
private:
int* xpData;
int* xpIndex;
int xLength;
};
//// ClassB only allocates a data buffer for use in ClassB_Base
class ClassB : public ClassB_Base
{
public:
ClassB(int maxSize)
: ClassB_Base(new int[maxSize], &xIndex, maxSize) {}
private:
int xIndex;
};
//// ClassA_Base acts on the data and calls ClassB
class ClassA_Base {
public:
ClassA_Base(ClassB_Base& ClassB_Passed_Ref)
: xClassB_Object_Ref(ClassB_Passed_Ref) {}
void ClassA_Action(int *data) {
//// Do some ClassA_Action stuff with the data like sort or filter
xClassB_Object_Ref.ClassB_Action(data);
}
private:
ClassB_Base& xClassB_Object_Ref;
};
//// ClassA only instantiates a class for use in ClassA_Base
class ClassA : public ClassA_Base {
public:
ClassA(int maxSize = 4000)
: ClassA_Base(xClassB_Object),
xClassB_Object(maxSize) {}
private:
ClassB xClassB_Object;
};
用例:
//// Now using the whole chain
class AppLevelClass1 : public ClassA {
public:
AppLevelClass1(void) {
ClassA_Action(xData);
}
int xData[10];
};
//// Or using part of the chain
class AppLevelClass2 : public ClassB {
public:
AppLevelClass2(void) {
ClassB_Action(xData);
}
int xData[10];
};
//// Or using another part of the chain
class AppLevelClass3 : public ClassB_Base {
public:
AppLevelClass3(void) : ClassB_Base(xBuff, &xIndex, 100) {
ClassB_Action(xData);
}
int xData[10];
int xIndex;
int xBuff[1000];
};
//// Other use cases
int main() {
int data[10];
int index;
AppLevelClass myAppLevelClass;
myAppLevelClass.ClassA_Action(data);
ClassB_Base xClassB_Base(data, &index, 5);
xClassB_Base.ClassB_Action(data);
ClassB xClassB(1000);
xClassB.ClassB_Action(data);
ClassA_Base xClassA_Base1(xClassB_Base);
xClassA_Base1.ClassA_Action(data);
ClassA_Base xClassA_Base(xClassB);
xClassA_Base.ClassA_Action(data);
ClassA xClassA(1000);
xClassA.ClassA_Action(data);
}
在 C++ 中,基 class 总是在派生 class 的任何部分构造之前构造。没有例外,没有解决方法,没有替代方案。在基础 class 及其构造函数(如果有)returns 完全构建之前,派生 class 的任何部分都不存在。这是基础 C++。
不过
C++ 的另一个基本部分是多重继承,通过多重继承,所有基 classes 总是按声明顺序构造(我忽略了虚拟继承,这增加了一些与此处无关的额外复杂性) .
这几乎是您可以用来调整构建顺序的唯一工具。但这可以为您的优势谨慎使用。例如,而不是第一个示例中显示的代码:
class ClassA : private ClassB, public ClassA_Base {
public:
ClassA(int maxSize = 4000)
: ClassB{maxSize},
ClassA_Base{static_cast<ClassB &>(*this)}
{
}
};
不是让 ClassB
成为 ClassA
的私有成员,而是从它私有继承;然后将对它的引用传递给 ClassA_Base
的构造函数。 ClassB
首先得到完全构造,然后 ClassA_Base
得到对它的引用。