在没有组合/装饰器的情况下,在父类之前初始化子类

时间:2020-11-10 19:33:40

标签: c++ c++11

我再次需要做这样的事情-
我需要先初始化向量,然后将其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)使用组合/装饰器,但是我想知道是否还有另一种方法。

请不要对原始指针发表评论。这只是父类和子类之间依赖关系的一个示例。

4 个答案:

答案 0 :(得分:5)

首先通过设计构造基类。没办法。但是,您可以引入第二个基类,并以所需的初始化顺序从基类继承。

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) {};
};

答案 1 :(得分:2)

为什么不将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速度甚至对您的代码来说都是问题。

答案 2 :(得分:2)

不建议将其作为解决方案,但可能会提示实际解决方案。您不能在基类构造函数中使用派生类的成员。但是,您可以在构造基础时使用对派生成员的引用或指针。您只需要注意在完全构造派生对象之后才取消引用它们。例如,这是“确定”:

#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];
}

答案 3 :(得分:2)

我去了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;
}