Виртуальные функции в иерархии классов - PullRequest
0 голосов
/ 06 апреля 2011

Полагаю, это не такой умный вопрос, но я потратил немало времени на него и до сих пор не скомпилировал

Не могли бы вы объяснить, почему?

Спасибо

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;
};

// Зоопарк Животный

#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;
}

// Панда

#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

// миан

#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 ]

1 голос
/ 06 апреля 2011

В main.cpp вы сначала включили Bear.h, и этот файл содержит определение std :: ostream & Bear :: print (std :: ostream & out). Это определение не охраняется

#ifndef BEAR
#define BEAR 
...
#endif

Второе включение в main - это Panda.h, а в Panda.h вы снова включаете Bear.h. И поскольку вы не защищаете Bear :: print, он включается во второй раз, и компилятор не работает, потому что он не знает, какое определение метода ему следует использовать.

Чтобы уменьшить вероятность возникновения таких ошибок, вы должны включать только объявление в ваши файлы * .h, тогда как все определения должны идти в * .cpp

0 голосов
/ 06 апреля 2011

Хорошо, глупый ответ, что вам нужно избавиться от

// #, включая «Bear.h» в Panda.

поэтому мой вопрос сейчас - почему?- Почему мне не нужно включать #include "Bear.h", поскольку Bear является частью моей иерархии наследования?Я думал, что компилятор должен увидеть определение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...