【问题标题】:C++ Object-oriented programmingC++ 面向对象编程
【发布时间】:2015-02-12 15:53:25
【问题描述】:

我有 1 个问题,因为我很好奇如何处理此类问题。 我有一个名为“Pracownik”(工人)的基类和 2 个由公共 Pracownik 制成的子类; - Informatyk(信息学) - Księgowy(会计师) 写课很容易。让它们变得非常快,但我对 main 有一个小问题,因为我正在帮助朋友编写程序,但我有一段时间没有使用 C++。所以:

这是我的头文件“funkcje.h”

#include <iostream>

using namespace std;


class Pracownik
{
 private:
  string nazwisko;
  int pensja;
 public:
  Pracownik(string="",int=0);
  ~Pracownik();
  string getNazwisko();
  int getPensja();
  friend double srednia_pensja(int,Pracownik);
};

class Informatyk : public Pracownik
{
 private:
  string certyfikat_Cisco;
  string certyfikat_Microsoft;
 public:
  Informatyk(string="",int=0, string="", string="");
  ~Informatyk();
  void info();
};

class Ksiegowy : public Pracownik
{
 private:
  bool audytor;
 public:
  Ksiegowy(string="",int=0, bool=false);
 ~Ksiegowy();
 void info();

};

double srednia_pensja(int,Pracownik);

这些是我的函数“funkcje.cpp”的定义

#include "funkcje.h"

Pracownik::Pracownik(string a,int b)
{
  nazwisko=a;
  pensja=b;
}

Pracownik::~Pracownik()
{
}

string Pracownik::getNazwisko()
{
  return nazwisko;
}

int Pracownik::getPensja()
{
  return pensja;
}



Informatyk::Informatyk(string a, int b, string c, string d) : Pracownik(a,b)
{
  certyfikat_Cisco=c;
  certyfikat_Microsoft=d;
}

Informatyk::~Informatyk()
{
}



Ksiegowy::Ksiegowy(string a, int b, bool c) : Pracownik(a,b)
{
  audytor=c;
}

Ksiegowy::~Ksiegowy()
{
}

void Informatyk::info()
{
  cout<<"Nazwisko pracownika: "<<Pracownik::getNazwisko()<<endl;
  cout<<"Pensja pracownika: "<<Pracownik::getPensja()<<endl;
  cout<<"Certyfikat Cisco: "<<certyfikat_Cisco<<endl;
  cout<<"Certyfikat Microsoft: "<<certyfikat_Microsoft<<endl;
}


void Ksiegowy::info()
{
  cout<<"Nazwisko pracownika: "<<Pracownik::getNazwisko()<<endl;
  cout<<"Pensja pracownika: "<<Pracownik::getPensja()<<endl;
  cout<<"Audytor: ";
  if(audytor)
    cout<<"Tak"<<endl;
  else
    cout<<"Nie"<<endl;
}



double srednia_pensja(int a,Pracownik *b)
{

  return 0;
}

最后是主要的!

#include <iostream>
#include "funkcje.h"

using namespace std;

int main()
{
  Pracownik lista[10];
  Pracownik *lista_wsk = new Pracownik[10];
  Informatyk a("Kowalski1",1000,"Cisco1","Microsoft1");
  Informatyk b("Kowalski2",2000,"Cisco2","Microsoft2");
  Informatyk c("Kowalski3",3000,"Cisco3","Microsoft3");
  Ksiegowy d("Kowalski4",4000,1);
  Ksiegowy e("Kowalski5",5000,0);

  lista[0]=a;
  lista[1]=b;
  lista[2]=c;
  lista[3]=d;
  lista[4]=e;

  Informatyk *ab = new Informatyk("Kowalski1",1000,"Cisco1","Microsoft1");
  Informatyk *ac = new Informatyk("Kowalski2",2000,"Cisco2","Microsoft2");
  Informatyk *ad = new Informatyk("Kowalski3",3000,"Cisco3","Microsoft3");
  Ksiegowy *ae = new Ksiegowy("Kowalski4",3000,1);
  Ksiegowy *af = new Ksiegowy("Kowalski5",3000,0);

  lista_wsk[0]=*ab;
  lista_wsk[1]=*ac;
  lista_wsk[2]=*ad;
  lista_wsk[3]=*ae;
  lista_wsk[4]=*af;

  for(int i;i<5;i++)
    {

      lista[i].info();
      cout<<endl;
    }
  cout<<endl;

  //  for(int i;i<5;i++)
  // {

      //        lista_wsk[i].info();
  //  }



  return 0;
}

好的,我的问题来了: 我必须创建一个充满基类对象“Pracownik”的数组。 次要我必须创建一个充满指向类“Pracownik”对象的指针的数组。 (希望这两个第一步正确完成) 接下来我必须写入数组 3 个 Informatic 类的对象和 2 个 Accountant 类的对象。 所以我手动创建了 5 个对象,并以 array[0]=a; 的方式将它们添加到数组中。我想这还是不错的。 接下来我必须使用 new 创建类似的对象并将其添加到指针数组中。所以我用new创建了数组,用new创建了指向对象的指针。 (希望那是正确的2)。 最后: 我必须在添加到数组对象时使用 info()。 这是我的主要问题,如果我的数组是“Pracownik”类型并且我想使用子类中的函数 info() 我应该怎么做?以及当我尝试使用“for”显示这些信息时,编译器将如何知道他是否应该使用来自 Accountant 或 Informatic 的 info()。

【问题讨论】:

  • 在课堂上提供virtual void info() = 0; Pracownik
  • 如果您可以将代码中的标识符翻译成英文,那将非常有帮助。您确实在问题中提供了一些翻译,但对于只会说英语的人来说,您的代码仍然难以阅读和理解。
  • 5gon12eder 对不起!希望我翻译的所有信息都足以理解代码。但无论如何,感谢您的帮助,我得到的答案忘记了这个对象切片和虚函数的存在。必须写一些程序;P 因为我开始忘记语言了。
  • 一句造福人类的智者的话:请用英文写代码。让一切变得非常简单。

标签: c++ object main


【解决方案1】:

Pracownik 的数组中,元素的类型为Pracownik。当您将元素复制到数组中时,有关对象属于 Pracownik 子类的任何信息都会丢失。

这称为对象切片,导致无法在这些对象上调用Informatyk::info()

如果要调用子类的方法,则必须通过在数组中存储指针或引用来防止对象切片。

【讨论】:

    【解决方案2】:

    正如Oswald 在他的回答中所说,

    Pracownik * lista_wsk = new Pracownik[10];
    

    分配一个包含 10 个 Pracownik 对象的数组。这可能不是你想要的。涉及到多态性,我们通常要处理指针或引用。因此,您需要一个 Pracownik * 指针数组。由于您在编译时已经知道它将有 10 个成员,因此这里不需要动态分配。我想你的意思是写

    Pracownik * lista_wsk[10];
    

    相反。现在我们不将对象而是指向对象的指针放入数组中。例如:

    lista_wsk[2] = new Informatyk("Kowalski3", 3000, "Cisco3", "Microsoft3");
    

    然后我们可以像这样遍历项目:

    for (unsigned i = 0; i < 10; ++i)
      std::cout << lista_wsk[i]->getNazwisko() << std::endl;
    

    正如您已经发现的那样,在超类对象上调用子类函数成员是不可能的。可以通过 cast 在运行时自己找出实际类型。

    for (unsigned i = 0; i < 10; ++i)
      if (Informatyk * info_ptr = dynamic_cast<Informatyk *>(lista_wsk[i]))
        info_ptr->info();
    

    dynamic_cast 在可能的情况下返回一个指向目标类的指针,否则返回一个nullptr(其计算结果为false,因此是有条件的)。但是请注意,这被认为是非常糟糕的风格。最好使用虚函数。因此,添加

    virtual void
    info()
    {
      // Do what is appropriate to do for a plain Pracownik.
      // Maybe leave this function empty.
    }
    

    到超类,再次到子类

    virtual void
    info()  // override
    {
      // Do what is appropriate to do for an Informatyk.
    }
    

    子类中具有相同签名的函数被称为覆盖从超类继承的函数。由于该函数被标记为virtual,编译器将生成额外的代码以在运行时确定要调用的函数版本。

    如果您正在编写 C++11,您可以通过在其类型之后放置关键字 override 来明确覆盖(取消注释 override)。我建议您使用它来避免因意外拼写错误或其他拼写错误而导致的错误。

    【讨论】:

      猜你喜欢
      • 2011-04-16
      • 1970-01-01
      • 2010-09-18
      • 1970-01-01
      • 1970-01-01
      • 2015-03-23
      • 1970-01-01
      • 1970-01-01
      • 2011-07-09
      相关资源
      最近更新 更多