试图创建不同类对象的单个数组

时间:2014-11-09 13:42:38

标签: c++ inheritance

我需要创建一个具有其属性的基类worker, 创建从Worker类继承的2个类ContractWorker和PartimeWorker 创建一个可容纳2个ContractWorker和2个PartimeWorker对象的数组。

#include<iostream>
#include<cstring>

using namespace std;

class worker
{

               int hrs;
               string name;
               int wage;
               public:
               worker():wage(200){}
             int pay(int hours)
             {
                 return(wage*hours);
             }
             worker (string nm,int hours)
             {
                    name=nm;
                    hrs=hours;
             };
};
class contract : public worker
{
      public:
             contract(){}
             void getsal(int hours)
             {
                      cout<<"\nSalary for "<<name<<" is "<<pay(hours);
                      cout<<"\nWorker is on contract\n";
             }
};
class part_time : public worker
{
      public:
             part_time(){}
             void getsal(int hours)
             {
                      cout<<"\nSalary for "<<name<<" is "<<pay(hours);
                      cout<<"\nWorker is part time\n";
             }
};
int main()
{
    worker *arr[4];
    string name="XYZ";
    int hours=10;

    arr[0]=new contract();
    arr[0].worker(name,hours);

    arr[1]=new contract();
    arr[1].worker(name,hours);

    arr[2]=new parttime();
    arr[2].parttime(name,hours);

    return 0;
}

我应该在派生类或基类函数的函数中传递name和hours属性的值?

以下错误 51请求会员&#39;工作人员&#39;在&#39; arr [0]&#39;中,它是指针类型&#39; worker *&#39; (也许你打算使用&#39; - &gt;&#39;?) 正在出现。

我对这个问题感到困惑。请帮忙。

此外,如何访问私人会员

2 个答案:

答案 0 :(得分:0)

您的代码存在很多问题。您遇到的主要问题是由以下几行引起的。

arr[0].worker(name,hours);
arr[1].worker(name,hours);
arr[2].parttime(name,hours);

要通过指针访问成员函数,您需要使用->运算符而不是.。不幸的是,即使这种更改在这里也不起作用,因为您无法以这种方式显式调用基类或派生类的构造函数。

您的代码还存在其他一些问题,您可以通过一些更改来解决此问题。

  • 您需要包含<string>而不是<cstring>
  • using namespace std;只是形式不好。
  • 派生类无法在构造期间将名称,工资和小时数传递给基类。这需要基类中的构造函数,它将name,wage和hours作为参数,并且要求派生类也这样做。
  • 基类中的默认构造函数可能不是您要完成的任务所必需的。
  • 派生类无法访问基类中的成员变量,因为它们是私有的。我建议在基类中添加一个访问器函数来检索名称。
  • 当您通过const引用更合适时,您会按值传递大量字符串。虽然传递值没有任何内在错误,但在这种情况下会产生不必要的副本。
  • 当您将对象指针添加到数组时,您会尝试通过显式调用基类的构造函数来初始化它们。你不能这样做,构造函数是没有名字的特殊成员函数,不能像这样调用。您需要从派生类的构造函数中执行此操作。
  • pay成员函数如果被声明为const,则会更好地提供服务,因为它不会修改任何成员变量。
  • 基类中的hours成员变量似乎没有必要,因为paygetsal都将小时作为参数。
  • 您的基类需要一个虚拟析构函数。

您的代码包含上面列出的大部分更正。

#include <iostream>
#include <string>

class worker
{
    std::string name;
    int wage;

public:

    //  constructor that takes name and wage by argument so member variables
    //  can be initialized during construction.
    worker(const std::string& name, int wage)
        : name(name), wage(wage)
    {
    }

    virtual ~worker() {}

    //  Declared const
    virtual int pay(int hours) const
    {
        return(wage*hours);
    }

    //  Added so base classes and free functions can access the name
    virtual const std::string& getName() const
    {
        return name;
    }

    //  Pure virtual requiring derived classes to provide a definition and
    //  allowing the function to be invoked through the base class interface.
    virtual void getsal(int hours) const = 0;
};

class contract : public worker
{
public:

    //  constructor that takes name and wage by argument so member variables
    //  can be initialized during construction.
    contract(const std::string& name, int wage)
        : worker(name, wage) {}

    void getsal(int hours) const
    {
        std::cout << "\nSalary for " << getName() << " is " << pay(hours);
        std::cout << "\nWorker is on contract\n";
    }
};

class part_time : public worker
{
public:

    //  constructor that takes name and wage by argument so member variables
    //  can be initialized during construction.
    part_time(const std::string& name, int wage)
        : worker(name, wage) {}

    void getsal(int hours) const
    {
        std::cout << "\nSalary for " << getName() << " is " << pay(hours);
        std::cout << "\nWorker is part time\n";
    }
};


int main()
{
    worker *arr[4];
    std::string name = "XYZ";
    int hours = 10;
    int wage = 100;

    //  construct the objects
    arr[0] = new contract(name, wage);
    arr[1] = new contract(name, wage);
    arr[2] = new part_time(name, wage);

    //  Calculate pay based on hours
    arr[0]->getsal(hours);

    return 0;
}

答案 1 :(得分:0)

让我们从头开始。

<强>构造

在C ++中,构造函数是类的特殊成员函数,与类本身具有相同的名称。它的作用是初始化类数据成员。

例如:

class Word {
public:
    Word(std::string w): data(w) {}

    std::string data;
};

此处,Word是一个类,可以通过传递std::string参数来构造,该参数用于初始化其data数据成员。

  • 没有声明任何构造函数的类使编译器生成类似于ClassName() {}的隐式默认构造函数
  • 如果数据成员未在初始化列表中初始化(:和开始{之间的内容),则默认初始化为;请注意,对于intPointer*,这意味着有一些未定义的值(可能是垃圾)
  • 如果一个类没有默认构造函数(即一个可以在没有任何参数的情况下调用的构造函数,因为它没有任何参数,或者它们都没有默认值),那么它就不能默认构造
  • 如果有多个构造函数,则根据参数列表选择“最佳匹配”,例如常规函数调用

在您的情况下,worker有两个构造函数,一个默认构造函数worker()和另一个构造函数worker(std::string name, int hours);既没有完全初始化WEIRD类。首先定义一个构造函数,该构造函数设置每个数据成员(尽管它可以将一些构造函数设置为默认值而不从参数中推导出所述值)。

在您的情况下,您尝试在现有对象(arr[1].worker(name, hours))上调用构造函数:这是无意义的,因为构造函数的作用是创建对象。请继续阅读。

<强>继承

继承用于扩展类。它应该主要用于满足Liskov替换原则的情况:即,在所有情况下,派生类行为应该满足基类给出的任何保证。

一般来说:

  • 你应该只尝试扩展一个原样的类:基类至少应该有一个virtual方法。
  • 一个至少有一个virtual方法的类也应该有一个virtual析构函数(注意:从至少一个具有virtual析构函数的类继承的类的析构函数是隐式的{ {1}})

示例:

virtual

默认情况下,派生类构造函数将调用基类默认构造函数;这可以通过直接从初始化列表中调用来更改:

class ISalaried {
public:
    virtual ~Salaried() {}

    virtual int getSalary(int hours, int overtime) const = 0;
};

class Employee: public ISalaried {
public:
    Employee(std::string name, int rate): name(name), rate(rate) {}

    // implicitly declared by the compiler for you
    // virtual ~Employee() {}

    // override is specific to C++11, if your compiler does not recognize it,
    // leave it off.
    virtual int getSalary(int hours, int overtime) const override {
        return rate * (hours + overtime);
    }

private:
    std::string name;
    int rate;
};

如果基类没有默认构造函数,则必须使用。

在您的情况下,这意味着您的派生类都应该从他们自己的构造函数中将名称和小时传递给class Derived: public Base { public: Derived(): Base(200, "42") {} // invokes a constructor of Base }; 构造函数。

此外,派生类无法访问其基类worker成员。您可以在基类中创建所述成员private或定义public getter成员函数,该函数不带参数并返回成员的值(每个参数一个getter)。

另一种选择是基类没有成员(仅提供接口)。

<强>目标

这里还有另一个问题,内存,但正确处理内存是一个完全独立的主题,我们已经超越了我们的复杂性预算。

因此,我会给你一个目标:所编写的public函数应该编译,更改你的mainworkercontract类来实现它。

part_time