如何从C ++中的基类访问派生类的属性?

时间:2016-02-02 02:58:33

标签: c++ oop

假设有一个名为Dog的基类,它具有以下属性和方法。

#pragma once
#include <string>

class CDog
{
protected:
string name;
string breed;
int age;

public:
CDog();
virtual ~CDog();
CDog(string name, string breed, int age);
string getName();
string getBreed();
int getAge();
};

两个派生类叫做Puppy和Old;

#pragma once
#include "CDog.h"
class CPuppy: public CDog
{
private:
bool playful;

public:
CPuppy();
~CPuppy();
CPuppy(string name, string breed, int age, bool playful);
bool getPlayful;
};

 #pragma once
#include "CDog.h"
class COld: public CDog
{
private:
bool disease;

public:
COld();
~COld();
COld(string name, string breed, int age, bool disease);
bool getDisease;
};

然后,我基于Dog类创建一个动态的对象向量,这样用户就可以根据需要注册多少只狗。后来,用户想知道所有小狗和所有老狗的平均年龄。我的问题在这里提出,¿如何在向量中访问Puppey和Old类的属性以生成这些报告?我认为必须有一个if语句,但我不知道这个条件。 我希望你能帮助我。 我使用两个不同的动态向量解决了这个问题,一个用于Puppey类,另一个用于Old类,但我不知道是否只能使用一个动态向量。

2 个答案:

答案 0 :(得分:1)

通常可以通过dynamic cast来实现。一个人会vector指向Base的指针,然后尝试将Base转发给Derved个对象,如果成功的话就像它一样工作#{1 (它是)。与示例中一样,或在此处:https://stackoverflow.com/a/6471659/1133179

然而,在c ++中,这几乎总是一个糟糕的设计和很少使用的模式。它可能只对实现动态语言有用。 c ++自然是一种静态类型语言,设计可以避免这些问题。

对于您的情况,您应该在基类中具有共同功能,例如Derived中的age,然后对于Dog的容器,您可以计算平均年龄。但是,如果您需要仅针对Dog的一种类型执行操作,则应将其放入另一个容器中,这样您就不会混用两种类型,也不必进行任何过滤,类型检查。

可能最好的设计是拥有两个shared_ptr的容器。一个用于SpecialDog(所有狗),一个用于CDog用于老狗。如果您创建了COld,则可以将其放入两个容器中,如果您创建COldCPuppy,则只能将其设置为CDog。我们的想法是拥有&#34;观点&#34;同类的对象。由于一个对象(一只狗)可以属于两个类,你需要表达对象在视图之间实际共享的信息,因此vector< shared_ptr<CDog> >

对于初学者来说,这可能不是最简单的,但它可能是最合适的方式。

答案 1 :(得分:0)

要做你想要的,你需要:

  1. 保留两个单独的列表,一个用于CPuppy个对象,另一个用于COld个对象,然后分别循环遍历:

    template<typename T>
    int getAverageAge(const std::vector<T*> &dogs)
    {
        if (dogs.empty()) return 0;
        int sum_ages = 0;
        for(std::vector<T*>::iterator iter = dogs.begin(), end = dogs.end(); iter != end; ++iter)
        {
            sum_ages += (*iter)->getAge();
        }
        return sum_ages / dogs.size();
    }
    

    std::vector<CPuppy*> puppies;
    std::vector<COld*> olds;
    ...
    int avg_puppy_age = getAveragAge(puppies);
    int avg_old_age = getAveragAge(olds);
    
  2. 使用dynamic_cast检查任何给定的CDog是否真的是CPuppyCOld个对象。

    std::vector<CDog*> dogs;
    ...
    
    int avg_puppy_age = 0;
    int num_puppies = 0;
    int avg_old_age = 0;
    int num_olds = 0;
    
    for(std::vector<CDog*>::iterator iter = dogs.begin(), end = dogs.end(); iter != end; ++iter)
    {
        if (dynamic_cast<CPuppy*>(*iter) != NULL)
        {
            avg_puppy_age += (*iter)->getAge();
            ++num_puppies;
        }
        else if (dynamic_cast<COld*>(*iter) != NULL)
        {
            avg_old_age += (*iter)->getAge();
            ++num_olds;
        }
    }
    
    if (num_puppies)
        avg_puppy_age /= num_puppies;
    if (num_olds)
       avg_old_age /= num_olds;
    
  3. 然后,您可以(并且应该)采用上述两种技术并将它们组合在一起:

    std::vector<CDog*> dogs;
    std::vector<CPuppy*> puppies;
    std::vector<COld*> olds;
    
    ...
    
    for(std::vector<CDog*>::iterator iter = dogs.begin(), end = dogs.end(); iter != end; ++iter)
    {
        if (CPuppy *puppy = dynamic_cast<CPuppy*>(*iter))
            puppies.push_back(puppy);
    
        else if (COld *old = dynamic_cast<COld*>(*iter))
            olds.push_back(old);
    }
    
    // alternatively, any time you add a new Puppy or Old to the
    // main dogs list, add it to the appropriate sub-list as well...
    
    int avg_puppy_age = getAveragAge(puppies);
    int avg_old_age = getAveragAge(olds);