假设有一个名为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类,但我不知道是否只能使用一个动态向量。
答案 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
,则可以将其放入两个容器中,如果您创建COld
或CPuppy
,则只能将其设置为CDog
。我们的想法是拥有&#34;观点&#34;同类的对象。由于一个对象(一只狗)可以属于两个类,你需要表达对象在视图之间实际共享的信息,因此vector< shared_ptr<CDog> >
。
对于初学者来说,这可能不是最简单的,但它可能是最合适的方式。
答案 1 :(得分:0)
要做你想要的,你需要:
保留两个单独的列表,一个用于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);
使用dynamic_cast
检查任何给定的CDog
是否真的是CPuppy
或COld
个对象。
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;
然后,您可以(并且应该)采用上述两种技术并将它们组合在一起:
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);