问题描述
我再次需要做这样的事情-
我需要先初始化向量,然后将其data()地址传递给父类。
#include <vector>
struct A{
A(int *a) : a(a){}
int *a;
};
struct B : A{
B() : A( v.data() ){}
std::vector<int> v { 1024 };
};
#include <cstdio>
int main(){
B b;
b.v[55] = 5;
printf("%d\n",b.a == b.v.data() );
printf("%d\n",b.a[55]);
printf("%d\n",b.v[55]);
}
这里的问题是向量在父类之后初始化并且v.data()
包含垃圾。我什至对此编译感到惊讶。
我知道我可以为此或受保护的成员setPtr(int *a)
使用组合/装饰器,但是我想知道是否还有另一种方法。
请不要对原始指针发表评论。这只是父类和子类之间依赖关系的一个示例。
解决方法
首先通过设计构造基类。没办法。但是,您可以引入第二个基类,并以所需的初始化顺序从基类继承。
struct a
{
int x;
a(int x) : x(x) {};
};
struct b
{
int *px;
b(int* px) : px(px) {};
};
struct derived : a,b
{
public:
derived(int x_) : a(x_),b(&x) {};
};
,
为什么不将A的初始化委派给构造函数以外的其他函数?
#include <vector>
struct A{
A() : a(nullptr) {}
void init(int* i_a) {
a = i_a;
}
int *a;
};
struct B : A{
B() : A(),v(1024) {
init(v.data());
}
std::vector<int> v;
};
#include <cstdio>
int main(){
B b;
b.v[55] = 5;
printf("%d\n",b.a == b.v.data() );
printf("%d\n",b.a[55]);
printf("%d\n",b.v[55]);
}
此外,为什么在C ++中使用printf
?这是相当不安全的。请改用std::cout
。与通常的看法相反,如果处理得当,它实际上没有比C stdio慢多少,而且我们不确定I / O速度甚至对您的代码来说都是问题。
不建议将其作为解决方案,但可能会提示实际解决方案。您不能在基类构造函数中使用派生类的成员。但是,您可以在构造基础时使用对派生成员的引用或指针。您只需要注意在完全构造派生对象之后才取消引用它们。例如,这是“确定”:
#include <vector>
#include <iostream>
struct A{
A(std::vector<int>* p) : p(p){}
std::vector<int>* p;
};
struct B : A{
B() : A( &v ){} // <- fine as long as A only stores the pointer
std::vector<int> v { 1024 };
};
int main(){
B b;
b.v[55] = 5;
std::cout << (b.p == &b.v) << "\n";
std::cout << (*b.p)[55];
}
,
我去了curiously recurring template pattern
#include <iostream>
#include <vector>
#include <stdio.h>
template <typename T>
struct Base {
int* raw_ptr = nullptr;
void Supply() {
(static_cast<T*>(this))->Supply();
}
};
struct Derived : public Base<Derived> {
std::vector<int> v { 1024 };
void Supply() {
raw_ptr = v.data();
}
};
template<typename T>
void SupplyBuffer(Base<T>* b) {
b->Supply();
}
int main()
{
Derived b;
SupplyBuffer(&b);
b.v[55] = 5;
printf("%d\n",b.raw_ptr == b.v.data() );
printf("%d\n",b.raw_ptr[55]);
printf("%d\n",b.v[55]);
return 0;
}