类层次结构中的虚函数

时间:2011-04-06 18:44:35

标签: class inheritance virtual

我认为这不是一个如此聪明的问题,但我花了相当多的时间在它上面但仍然没有编译

你能解释一下原因吗?

由于

1>------ Build started: Project: Ch17, Configuration: Release Win32 ------
1>  p731.cpp
1>\\na-13\agnolucp\my documents\visual studio 2010\projects\ch17\ch17\Bear.h(29): error     C2084: function 'std::ostream &Bear::print(std::ostream &) const' already has a body
1>          \\na-13\agnolucp\my documents\visual studio 2010\projects\ch17\ch17\Bear.h(19) : see previous definition of 'print'
1>p731.cpp(16): error C2264: 'Bear::print' : error in function definition or declaration; function not called
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

//濒危

#ifndef ENDAGERED
#define ENDAGERED
#include <iostream>


class Endangered {
public:
     //virtual ~Endangered();
     virtual std::ostream& print(std::ostream&) const;
     // virtual so needs to be defined otherwise error
     virtual void highlight() const;
};

// ZooAnimal

#ifndef ZOOANIMAL
#define ZOOANIMAL
#include<string>
class ZooAnimal {
public:
    ZooAnimal();
    ZooAnimal(std::string animal, bool exhibit,
              std::string family): Name(animal), 
                                   OnExhibition(exhibit), 
                                   FamilyName(family) { } 
    //virtual ~ZooAnimal();

    virtual std::ostream& print(std::ostream&) const;

    // accessors
    std::string getName() const { return Name; }
    std::string getFamilyName() const { return FamilyName; }
    bool getOnExhibition() const { return OnExhibition; }
    // ...
protected:
    std::string Name;
    bool        OnExhibition;
    std::string FamilyName;
    // ...
private:
};

std::ostream& ZooAnimal::print(std::ostream &out) const {
    return out << "I am printing ZooAnimal" << std:: endl;
}




#endif




void Endangered::highlight() const {
    std::cout << "HIGHLIGHT: HEY, I AM IN DANGER" << std::endl;
}


std::ostream& Endangered::print( std::ostream &out ) const {
    // thsi would be fine
    // return out << "I Aa Printing Endangered" << std::endl;
    out << "I Aa Printing Endangered" << std::endl;
    return out;
}


#endif

//承担

#ifndef BEAR
#define BEAR

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

class Bear : public ZooAnimal {
enum DanceType { two_left_feet, macarena, fandango, waltz };
public:
    Bear();
    //listing all arguments
    // passing BaseClass constructor in initialiser list
    Bear(std::string name, bool onExhibit=true, 
         std::string family = "Bear"):
              ZooAnimal(name, onExhibit, family),
              ival(0), dancetype(macarena) { }

    virtual std::ostream& print(std::ostream&) const;
    void dance() const;

    //virtual ~Bear();
private:
    int         ival;
    DanceType   dancetype;
};
#endif

std::ostream& Bear::print(std::ostream &out) const {
    return out << "I am printing Bear" << std:: endl;
}

// panda

#ifndef PANDA
#define PANDA

#include <iostream> 
#include "Bear.h"
#include"Endangered.h"

class Panda : public Bear, public Endangered {
public:
    Panda();
    Panda(std::string name, bool onExhibit=true);
    // virtual ~Panda();
    // mentioning virtual would not be necessary
    virtual std::ostream& print(std::ostream&) const;
    // mentioning virtual would not be necessary
    virtual void highlight() const  {
        std::cout << "HIGHLIGHT: Hey I am Panda" <<std::endl;
    }
};


std::ostream& Panda::print(std::ostream &out ) const {
    // this would be fine
    // return out << " I am printing Pandaa" << std::endl;
    out << "I am printing Panda" << std::endl;
    return out;

}


Panda::Panda(std::string name, bool onExhibit)
        : Bear(name, onExhibit, "Panda") { }

void Bear::dance() const {
    switch(dancetype) {
        case two_left_feet: 
            std::cout << "I am doing two_left_feet"<< std::endl;
            break; 
        case macarena:  
            std::cout << "I am doing macarena"<< std::endl;
            break; 
        case fandango: 
            std::cout << "I am doing fandango"<< std::endl;     
            break;          
        case waltz: 
            std::cout << "I am doing waltz"<< std::endl;
            break; 
    }
}


# endif

// mian

#include "Bear.h"
#include "Panda.h"
#include "ZooAnimal.h"

#include<iostream>
#include<string>

int main () {

    Endangered a; 
    ZooAnimal b("John", true, "DiMonte");
    //b.print(std::cout);
    Bear c("Luigi");
    c.dance();
    c.print(std::cout);
    Panda d("Luigi");
    d.print(std::cout);
    d.highlight();
    d.dance();
    Panda e();
}

2 个答案:

答案 0 :(得分:1)

在main.cpp中,你首先包含了Bear.h,这个文件包含了std :: ostream&amp;的定义。 Bear :: print(std :: ostream&amp; out)。

没有保护这个定义
#ifndef BEAR
#define BEAR 
...
#endif

第二个包括主要是Panda.h和Panda.h你再次包括Bear.h.而且因为你没有守护Bear :: print,所以第二次包含它并且编译器失败,因为它不知道它应该使用哪种方法定义。

为了减少此类错误的发生,您应该只在* .h文件中包含声明,而所有定义都应该转到* .cpp

答案 1 :(得分:0)

好的愚蠢的答案是你需要摆脱

//#包括Panda中的“Bear.h”。

所以现在我的问题 - 为什么? - 为什么我不需要包含#include“Bear.h”,因为Bear是我的继承层次结构的一部分?我认为编译器需要看到定义。