不允许使用抽象类类型“Animal”的对象:(C ++)

时间:2011-09-29 06:08:31

标签: c++ visual-c++

我正在尝试将内容存储到矢量中,但问题很少。 这些是我的代码。

Animal.cpp

#include "Animal.h"
#include "Cattle.h"
#include "Sheep.h"
#include <iostream>
#include <string>
using namespace std;

Animal::Animal(int newid, double newweight, int yy, int mm, int dd, double newaccDose, char newsex)
{
    id = newid;
    weight = newweight;
    yy = yy;
    mm = mm;
    dd = dd;
    dose = newaccDose;
    sex = newsex;
}

Animal::Animal()
{
    id = 0;
    weight = 0;
    yy = 0;
    mm = 0;
    dd = 0;
    dose = 0;
    sex = ' ';
}

Animal::~Animal(){}

double Animal::getDaysDifference(){
    jdate dateOfBirth(dd,mm,yy);
    jdate now;
    double diff = now-dateOfBirth;
    return diff;
}

void Animal::addAnimal(){
    int select=0;
    int id;

    cout << "1.  Cattle    2.  Sheep" << endl;
    cout << "Select a type of animal: ";
    cin >> select;

    if(select==1){
        Cattle* c1;
        cout << "Please answer following questions" << endl;
        cout << "Type the animal's ID: ";
        cin >> id;

        c1->setID(id);

        //vector<Animal> vec;
        //vector<Animal>::iterator vec_ite;

    }else if(select==2){
        Sheep* s1;
        cout << "Please answer following questions" << endl;
        cout << "Type the animal's ID: ";
        cin >> id;

        s1->setID(id);
    }
    else{
        cout << "Invalid number please try again" << endl;  
    }
}

首先,在上面的代码Cattle* c1Sheep* s1中,它没有错误。 即使我像s1->setID(id)那样编码也没关系。然而,

Cattle.cpp

#include "Cattle.h"

Cattle::Cattle(int newid, double newweight, int yy, int mm, int dd, 
           double newdose, char newsex, string newcategory)
    : Animal(id, weight, yy,mm,dd, dose, sex)
{
    id = newid;
    weight = newweight;
    dose = newdose;
    sex = newsex;
    Cattle::category = newcategory;
}

Cattle::Cattle(){
    id = 0;
    weight = 0;
    dose = 0;
    sex = ' ';
    Cattle::category = "";
}

Cattle::~Cattle(){}

string Cattle::getCategory(){
    return category;
}

double Cattle::calcDose(){
    Cattle* c1;
    if(c1->getDaysDifference() < 90 || c1->getCategory() == "Meat"){
        c1->dose = 0;
        return c1->dose;
    }
    else if(c1->getCategory() == "Dairy"){
        if (c1->weight < 250 || c1->dose > 200){
            c1->dose = 0;
        }
        else{
            c1->dose = c1->weight * 0.013 + 46;
        }
        return c1->dose;
    }
    else if(c1->getCategory() == "Breeding"){
        if (c1->weight < 250 || c1->dose > 250){
            c1->dose = 0;
        }
        else{
            c1->dose = c1->weight * 0.021 + 81;
        }
        return c1->dose;
    }
    else
    {
        cout << "It is not valid category" << endl;
    }
}

Animal.h

#ifndef ANI_H
#define ANI_H
#include <vector>
#include "Treatment.h"
#include "jdate.h"

class Animal{
protected:
    int id;
    double weight;
    int yy;
    int mm;
    int dd;
    double dose;
    char sex;
    //Treatment treatArray[];
public:
    Animal();
    Animal(int newid, double newweight, int yy, int mm, int dd, double newdose, char newsex);
    ~Animal();

    virtual double calcDose() = 0;
    void addAnimal();
    double getDaysDifference();
};
#endif

DrugAdmin.cpp(主要)

#include <iostream>
#include "Animal.h"
#include "Cattle.h"
using namespace std;

int main(){
    Animal* a1=new Animal;
    delete a1;

    a1->addAnimal();
}

问题在这里,当我尝试定义Animal* a1=new Animal; delete a1;时,它说Object of abstract class type "Animal" is not allowed: 我在这里和那里使用Google搜索和Binged,我发现我无法定义抽象基类本身但是子类。 所以我使用Cattle.cppCattle c1=new Cattle;中尝试了同样的事情,但它也不起作用..

我真的不确定那是什么问题.. 你能帮帮我吗?

干杯

3 个答案:

答案 0 :(得分:5)

virtual double calcDose()

这说“对于动物的一切都可以calcDose(),不同的动物可能会做不同的事情......”

= 0;

“......但是动物没有'通用'的方法;每个人都必须指定自己的方法”。

您可能无法构建未指定的Animal类型,因为根据定义,缺少一条关键信息:如何calcDose为它。

这一切都很好。机会是,你真的不想建造一个未指明的动物,原因同样在现实生活中,你不会去农场(动物园?宠物商店?)购买“动物”而没有任何特定的偏见你想要什么样的动物。

存在类型Animal,以便您可以在适当的时候省略有关什么类型的动物的信息。在您的情况下,创建实例不是其中之一。


此外,addAnimal绝对没有感觉作为Animal的成员函数,无论您认为它有多少。有三个基本问题:

1)因为它是一个非静态成员函数,所以你需要Animal来调用该函数。那是一种捕获22。

2)您无法将动物添加到。你需要某种容器。

3)从概念上讲,制作动物清单不是动物的责任。无论谁需要清单,都是责任。

4)一般而言,在要求用户提供信息的代码与对该信息起作用的代码之间进行清晰分离是一个很好的策略。写一个 free (意思是,不是类的一部分)函数,要求提供信息,构造Animal和返回那个指针;然后在调用代码中,将指针存储在容器中。

除非你不想真的想使用原始指针。您应该使用某种智能指针,或者将指针放入boost ptr_container之一。

答案 1 :(得分:3)

Animal是一个抽象类,这意味着它具有虚拟函数。这是Animal中的纯虚函数。

virtual double calcDose() = 0;

无法创建抽象类的对象。不仅在C ++中,而且在所有面向对象的语言中都是如此,无论哪种支持虚函数(某些语言,如C#,都称之为abstract方法。)

如果删除声明中=0部分的纯说明符,如下所示:

virtual double calcDose() = 0;
                       //^^^^ this is called pure specifier

然后它将成为虚拟功能(与虚拟功能相对)。现在,您要定义虚拟函数,然后可以创建Animal的对象,因为它不再是抽象类。

答案 2 :(得分:1)

Animal中,您有:

virtual double calcDose() = 0;

因此该类是抽象的,无法实例化。您只能构造从它派生的类的对象实现该方法。