C++ 当 derived 和 base class 具有不同类型的参数时,我在继承方面遇到了一些严重的问题,如下所示:

C++ I have some seryous issues with inheritance when derived and base class have different types of parameters, like shown below:

我是 c++ 的新手,最近发现了 classes;

我学习了构造函数、重载运算符、三原则,现在我尝试学习继承。

我创建了 4 classes: 2 parents, 2 childs, 但我在 class parent1

这是class parent1:

class parent1{

protected:
    float slr;
    int age;
    char *name;
    void set_new_name(char ch[10001]);

public:

    parent1()
    {
        slr=0.0;
        age=0;
        name=NULL;
    }

    parent1(char ch[10001], float sl, int ag)
    {
        slr=sl;
        age=ag;
        set_new_name(ch);
    }

    parent1(const parent1 &p1)
    {
        char temp[10001];
        strcpy(temp,p1.name);

        if(name != NULL)
            delete[] name;
        set_new_name(temp);
        slr=p1.slr;
        age=p1.age;
    }

    parent1 &operator=(const parent1 &p1)
    {
        /// same lines as in copy constructor above
        return *this;
    }

    char* get_name() const;
    void print1();

    ~parent1()
    {
        delete[] name;
    }
};

这是他的childclass,child1:

class child1 : public parent1{

protected:

    int id;
    void set_id(int j);

public:

    child1(): parent1()
    {
        set_id(0);
    }

    child1(char ch[10001],float sl, int ag, int j): parent1(ch,sl,ag)
    {
        set_id(j);
    }

    child1(const child1 &p2): parent1(p2)
    {
        set_id(p2.get_id());
    }

    child1 &operator=(const child1 &p2)
    {
        set_id(p2.get_id());
        parent1::operator=(p2);
    }

    int get_id() const;
    void print2();
};

有class parent 2:

class parent2{

protected:

    char *name1;
    char *name2;
    void set_new_name1(char ch1[10001]);
    void set_new_name2(char ch2[14]);

public:

    parent2()
    {
        name1=NULL;
        name2=NULL;
    }

    parent2(char ch1[10001], char ch2[14])
    {
        set_new_name1(ch1);
        set_new_name2(ch2);
    }

    parent2(const parent2 &p3)
    {
        char temp2[10001];
        strcpy(temp2,p3.name1);
        if(name1 !=NULL)
            delete[] name1;
        set_new_name1(temp2);

        /// .. . same lines as above, this time for name2 and p3.name2
    }

    parent2 &operator=(const parent2 &p3)
    {
        /// .. same lines as in copy constructor above

        return *this;

    }

    char* get_name1() const;
    char* get_name2() const;
    void print3();

    ~parent2()
    {
        delete[] name1;
        delete[] name2;
    }

};

还有他的child,child2:

class child2: public parent2{

protected:
    char *job;
    void set_new_job(char ch3[15]);

public:

    child2(): parent2()
    {
       job=NULL;
    }

    child2(char ch1[10001], char ch2[10001],char ch3[11]): parent2(ch1,ch2)
    {
        set_new_job(ch3);
    }

    child2(const child2 &p4): parent2(p4)
    {
        char temp6[11];
        strcpy(temp6, p4.job);
        if(job != NULL)
            delete[] job;
        set_new_job(temp6);
    }

    child2 &operator=(const child2 &p4)
    {
        /// same lines as in copy constructor
        parent2::operator=(p4);
    }

    char* get_job() const;
    void print4();

    ~child2()
    {
        delete[] job;
    }
};

如你所见,class parent1 有 3 种类型的参数(一种浮点型、一种整型和一种字符*)。

Nonte: set_ functions works ok, get_functions just return class parametes (also works ok), print functions just print classes参数(例如:cout << name1;也可以正常工作)

问题是当我在 main 中创建 objects 时,这段代码拒绝工作。 一开始我以为是 operator= 被重载了很多次,结果是 parent1 的 float 参数 主要有:

char ch[10001]="my name", ch1[10001]="my name 1", ch2[14]="my name 2", ch3[11]="some code";
    int ag=10;
    float sl=10.1;

    parent1 o1;
    o1=parent1(ch,sl,ag);
    o1.print1();
    parent1 o2(o1);
    o2.print1();

    child1 o3;
    o3=child1(ch,sl,ag,3);
    o3.print2();

    child1 o4;
    o4=child1(ch,sl,ag,6);
    o4.print2();
    o4=o3;
    o4.print2();

    parent2 o5;
    o5=parent2(ch1,ch2);
    o5.print3();

    child2 o6(ch1,ch2,ch3);
    o6.print4();

似乎唯一 运行 是:

我知道我剪的代码很长,但是帮助我了解我需要什么解决这个愚蠢的错误!

我发现代码中至少有 3 个问题会导致 crash/undefined 行为。

第一个:

parent1(const parent1 &p1)
{
    char temp[10001];
    strcpy(temp,p1.name);

    if(name != NULL)             // name isn't initialized yet,
        delete[] name;           // these 2 lines shouldn't be here
    set_new_name(temp);
    slr=p1.slr;
    age=p1.age;
}

其次:(这些是启用警告时编译器报告的)

child1 &operator=(const child1 &p2)
{
    set_id(p2.get_id());
    parent1::operator=(p2);
    return *this;               // this line is missing
}

第三名:

child2 &operator=(const child2 &p4)
{
    char temp7[11];
    strcpy(temp7, p4.job);
    if(job != NULL)
        delete[] job;
    set_new_job(temp7);
    parent2::operator=(p4);
    return *this;               // this line is missing
}

return 语句不是“继承”的。每个应该 return 的功能都必须这样做。

通过这些更改,代码运行:

my name
my name
3
6
3
my name 1
my name 2
some code

(Live demo)

一些额外的改进说明:

char ch[10001] 这样的数组不能真正成为 C++ 中的函数参数。当它用作参数时,它会默默地衰减到 char *。因此,您不妨将所有 char ch[10001] 替换为 const char* ch(更好的是 std::string),以避免混淆。

此外,分配 temp 数组没有意义。你可以直接做 set_new_name(p1.name):

parent1(const parent1 &p1)
{
    set_new_name(p1.name);
    slr=p1.slr;
    age=p1.age;
}

花一些时间熟悉调试器是明智的。不进行调试就几乎不可能创建一个可以工作的应用程序。并启用编译器警告。使用 GCC 使用 -Wall -Wextra,使用 MSVC - /W4.

这是使用 std::string 的代码示例。感谢 std::string 我们可以遵循 0:

的规则
class parent1 {

protected:
  float slr = 0;
  int age = 0;
  string name;
  void set_new_name(string const &ch) { name = ch; }

public:
  parent1() {}

  parent1(string const &name, float slr, int age)
      : slr(slr), age(age), name(name) {}

  string const &get_name() const { return name; }
  void print1();
};

void parent1::print1() { cout << get_name() << '\n'; }

class child1 : public parent1 {

protected:
  int id = 0;
  void set_id(int j) { id = j; }

public:
  child1() : parent1() {}

  child1(string const &name, float sl, int ag, int j)
      : parent1(name, sl, ag), id(j) {}

  int get_id() const { return id; }
  void print2();
};

void child1::print2() { cout << get_id() << '\n'; }

class parent2 {

protected:
  string name1;
  string name2;

  void set_new_name1(string const &ch) { name1 = ch; }
  void set_new_name2(string const &ch) { name2 = ch; }

public:
  parent2() {}

  parent2(string const &name1, string const &name2)
      : name1(name1), name2(name2) {}

  string const &get_name1() const { return name1; }
  string const &get_name2() const { return name2; }
  void print3();
};

void parent2::print3() {
  cout << get_name1() << '\n';
  cout << get_name2() << '\n';
}

class child2 : public parent2 {

protected:
  string job;
  void set_new_job(string const &ch) { job = ch; }

public:
  child2() : parent2() {}

  child2(string const &name1, string const &name2, string const &job)
      : parent2(name1, name2), job(job) {}

  string const &get_job() const { return job; }
  void print4();
};

void child2::print4() { cout << get_job() << '\n'; }

这有效 equally well