简体   繁体   English

将数组指针从派生类传递到基类C ++

[英]Passing array pointer from derived class to base class C++

I'm trying to understand inheritance in C++. 我试图了解C ++中的继承。

I want to dynamically create an array in a derived class and pass the array pointer to the base class, and then the base class fills in the array. 我想在派生类中动态创建一个数组,并将数组指针传递给基类,然后基类填充该数组。 Finally I want to print the array from the derived class. 最后,我想从派生类中打印数组。

I wrote the following code but when I run this, the program crashes and I get a segmentation fault error. 我编写了以下代码,但是当我运行此代码时,程序崩溃并出现分段错误错误。

How should I implement this?! 我应该如何实现呢?

class Base {
private:
    int* array;
public:
    Base(int* a) {
        array = a;
        for(int i = 0 ; i < 10 ; i++) {
            array[i] = i;
        }
    }
};

class Child : public Base {
private:
    int* array;
public:
    Child() : array(new int[10]), Base(array) {}
    void print() {
        for(int i = 0 ; i < 10 ; i++) {
            cout << array[i] << endl;
        }
    }
};

The problem here is that the order of items in the initializer list does not influence the order in which the initialization is actually performed; 这里的问题是初始化器列表中项目的顺序不会影响实际执行初始化的顺序。 only the order in which the members are declared is considered. 仅考虑成员的声明顺序。 Moreover, the initialization of the base always happens first. 此外,基数的初始化总是首先发生。

Therefore, the Child constructor is actually executed as follows: 因此, Child构造函数实际上按以下方式执行:

  • Base(array) is invoked ( array is not set here!) Base(array)被调用(此处未设置array !)
  • array is assigned a valid value. array分配了有效值。

Fortunately, all you need to do to fix this problem is to remove the array from the Child : it is redundant anyway: 幸运的是,解决此问题所需要做的就是从Child删除array :无论如何这都是多余的:

class Child : public Base {
public:

    Child() : Base(new int[10]) {
    }

    void print() {
        for(int i = 0 ; i < 10 ; i++) {
            // Make a[] protected in the parent
            cout << a[i] << endl;
        }
    }
};

class Base
{
protected:
    int *array;
...
}

If you would rather not make a protected in the parent, you can fix your code as follows ( demo ): 如果您不想在父级中a受保护的对象,则可以按以下方式修复代码( 演示 ):

Child() : Base(array = new int[10]) {}

This is suboptimal, though, because a redundant member is kept in all instances of Child . 但是,这是次优的,因为在Child所有实例中都保留有一个冗余成员。

Base subobjects are initialised before class members, even if you write the initialisers in another order. 即使您以其他顺序编写初始化程序,也会在类成员之前初始化基础子对象。 So here: 所以在这里:

Child(): array(new int[10]), Base(array)

the Base object is initialised first, using the uninitialised value of array . 首先使用array的未初始化值初始化Base对象。

Solutions include: 解决方案包括:

  • make Base::array accessible from Child , so it doesn't need its own copy; 使Base::array可从Child访问,因此不需要它自己的副本;
  • move print into the base class, so that Child doesn't need to access array ; print移到基类中,这样Child不需要访问array
  • do something nasty like Child() : Base(array = new int[10]) , if you really need a redundant copy of an inaccessible variable for some reason. 如果出于某种原因确实需要冗余的不可访问变量副本,请执行Child() : Base(array = new int[10])这样的讨厌操作。

Make sure you've enabled compiler warnings; 确保已启用编译器警告; they should have caught this error. 他们应该已经抓住了这个错误。

It's because the base object is constructed first, and only then the child is constructed. 这是因为首先构造了基础对象,然后才构造了子对象。

This means that your array is unintialised. 这意味着您的阵列是未初始化的。

Put some tracing message at the begin and end of each of your consutructors, and you'll get a better understanding of how things work. 在每个构造器的开头和结尾处都添加一些跟踪消息,您将更好地了解其工作方式。

One solution would be to use std::array instead of raw pointer like the example below: 一种解决方案是使用std::array而不是原始指针,如下例所示:

#include <iostream>
#include <array>

template<typename T, std::size_t N>
class Base
{
private:
    std::array<T, N> const &array;
public:
    Base(std::array<T, N> const &a) : array(a) { }
    void print() const {
      std::cout << "Printing array from Base class!" << std::endl;
      for(auto i : array) std::cout << i << " ";
      std::cout << std::endl;
    }
};

template<typename T, std::size_t N>
class Child : public Base<T, N> {
private :
  std::array<T, N> array;
public:
  Child() : Base<T, N>(array) { 
    for(auto &i : array) i = 10;
  }

  void print() {
    std::cout << "Printing array from Child class!" << std::endl;
    for(auto i : array) std::cout << i << " ";
    std::cout << std::endl;
  }
};

auto main() -> int {
  Child<int, 10> c;
  c.print();
  Base<int, 10> *b = &c;
  b->print();

  return 0;
}

Live Demo 现场演示


Thus: 从而:

  • You wouldn't have to worry about releasing previously allocated memory. 您不必担心释放先前分配的内存。

  • Your Base class keeps a constant reference to the array object of the Child class. 您的Base类对子类的数组对象保持不变的引用。 Thus, you save memory. 因此,您可以节省内存。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM