【问题标题】:Trouble passing array of child class as parameter to child of parent class in C++在 C++ 中将子类的数组作为参数传递给父类的子类时出现问题
【发布时间】:2019-09-16 20:40:01
【问题描述】:

我有一个抽象父类,我们称它为 A,以及从它继承的三个子类:a_B、a_C 和 a_D。我有一个排序方法,它应该能够根据从父级 A 继承的评级属性对这些类(a_B、a_C 或 a_D)中的任何一个的数组进行排序。

但是,我在实现这一点时遇到了麻烦。

这基本上是我所拥有的:

class A {
protected:
    int rating;
    A(int r) {
        this->rating = r;
    }
public:
    int getRating() {
        return rating;
    }
    virtual void abstractStuff() = 0;
}

class a_B : public A {
    int property;
public:
    a_B(int r, int p) : A(r) {
        this->property = p;
    }
    void abstractStuff() {
        cout << "a_B" << endl;
    }
}


class a_C : public A {
    float property;
public:
    a_B(int r, float p) : A(r) {
        this->property = p;
    }
    void abstractStuff() {
        cout << "a_C" << endl;
    }
}


class a_D : public A {
    string property;
public:
    a_B(int r, string p) : A(r) {
        this->property = p;
    }
    void abstractStuff() {
        cout << "a_D" << endl;
    }
}


void sort(A* arr[]) {
    //sort implementation
}


int main() {
    a_B arr[5];
    //code to give each element of arr unique properties
    sort (arr); //doesn't work; this is where I'm kind of unclear about what to do
}

我对 arr 进行排序的最后一部分不清楚。我不确定是否应该将 a_B* 作为指针传递,或者将其转换为 A 类型,例如 (A) a_B(A*) a_B 或类似的东西。

编辑:

编译器给我一个invalid conversion from a_B to A**的错误。

【问题讨论】:

  • 您的基类构造函数应该是公共的,rating 变量应该是私有的。使用 protected 是一种代码味道。

标签: c++ pointers parameter-passing


【解决方案1】:

您的 sort 函数肯定将一组指向基类 A 的指针作为唯一参数。可能,这个想法是实现类型擦除(放置在不同动态类型的数组元素中),并且您将能够以多态方式处理元素。因此,您的 arr 参数将包含 A* 类型的元素,当您从数组中提取某些元素时,您可以提取其评级成员以进行排序。很重要,你需要改成

a_B arr[5];到 A* arr[5];

另外,每个类的构造函数都与类同名,所以如果我们假设你输入错误,例如类 a_D 应该是这样的

class a_D : public A {
    string property;
public:
    a_D(int r, string p) : A(r) {
        this->property = p;
    }
    void abstractStuff() {
        cout << "a_D" << endl;
    }
}

还要提一下,A 作为基类,在像你这样的实现中,应该有虚拟析构函数,否则你会有泄漏!!!

此外,要填充要传递给排序的数组,您需要在堆栈或堆(您选择堆栈)上为数组分配某种空间,但无论如何都要小心生命周期问题。曾经,当你有空间存放 A* 数组的元素时,每个元素都可以用 A* 填充,它可以用 a_B* 或 a_C* 或指向 A 的任何派生类的对象的指针进行初始化。这样的数组,你可以通过将函数作为参数排序,不进行任何转换。

示例代码,你应该可以编译运行了:

#include <iostream>
using namespace std;
class A {
    protected:
        int rating;
    A(int r) {
        this->rating = r;
    }
public:
    int getRating() {
        return rating;
    }
    virtual ~A(){} 
    virtual void abstractStuff() = 0;
};

class a_B : public A {
    int property;
public:
    a_B(int r, int p) : A(r) {
        this->property = p;
    }
    void abstractStuff() {
        cout << "a_B" << endl;
    }
};


class a_C : public A {
    float property;
public:
    a_C(int r, float p) : A(r) {
        this->property = p;
    }
    void abstractStuff() {
        cout << "a_C" << endl;
    }
};


class a_D : public A {
    string property;
public:
    a_D(int r, string p) : A(r) {
        this->property = p;
    }
    void abstractStuff() {
        cout << "a_D" << endl;
    }
};

template<class T, size_t N>
void printRatings(T*(&arr)[N]) {
    for (size_t i=0; i<N; ++i) {
        cout<< "rating["<< i <<"] = " << arr[i]->getRating() << "\n";
    }
}


int main() {
    A* arr[5];

    a_B b(1,1);
    a_C c(2,2.);
    a_D d(3,"3");

    arr[0] = &b;
    arr[1] = &c;
    arr[2] = &d;
    arr[3] = &c;
    arr[4] = &b;
    printRatings (arr); //this works
    return 0;
}

注意,我使用了模板函数 printRatings 指向类型 T 的指针数组并推导出数组大小,因此它可以安全地遍历它。 您可以使用相同的想法来制作排序功能,如下所示:

template<class T, size_t N>
void sort(T*(&arr)[N]) {
    // sorting impl
}

您将能够将 A* arr[5] 参数传递给它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-30
    • 2021-02-13
    • 1970-01-01
    • 1970-01-01
    • 2020-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多