继承实现只是感觉不对,我需要理由...... [英] Inheritance implementation just feels wrong, I need reasons though...

查看:52
本文介绍了继承实现只是感觉不对,我需要理由......的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试了一个小时,找到一些关于

的具体信息的参考,为什么这个特殊的继承实现是一个坏主意,但是

不能。如果以前已经回答过这个问题我很抱歉。这是

场景:


我们有一个包含所有虚函数的基类。我们称之为

Animal类。然后我们制作了两个类Fish和Bird,它们都继承了动物的
。在程序中,我们有一个动物指针数组

将容纳所有鱼和鸟对象。在大多数情况下,

他们共享功能(吃,呼吸等),所以你可以只用

来调用AnimalArray [i] - > Eat(并且它以多态方式处理。这是

我的问题,让我们说你想把一个RuffleFeathers函数添加到Bird类的
。现在为了仍然调用

AnimalArray [i] - > RuffleFeathers(),我必须将该函数

定义添加到Animal类中,即使不是全部动物将有b $ b b羽毛。所以我只是在Animal类中添加了一个虚函数声明和一个带有

a返回语句的存根,所以如果我调用

AnimalArray [i] - > RuffleFeathers()on一个Fish对象,它只会执行动物中定义的存根的
。对我来说,这样做是错误的。

方式。


这就是代码的样子:


class Animal {


virtual void Eat(){return;}

virtual void RuffleFeathers(){return;}

};

class Bird:public Animal {


void Eat(){printf(" Eat a mouse。);; }

void RuffleFeathers {printf(" Feathers ruffled。")};

};

class Fish:public Animal {


void Eat(){printf(吃一些海带。);}

};

int main()

{

动物* animalArray =新动物[100];

animalArray [0] =新鱼();

animalArray [1] =新鸟();


animalArray [0] - >吃();

}


现在把这个小例子扩展到10个继承

的类,大约有6个左右的函数,比如RuffleFeathers,

有与...无关y其他继承的类。事情

是实现工作,你不必在调用函数之前对单个数组中的每个元素进行类型检查

或强制转换。

你也不必保留每种类型的多个数组。但它只是

似乎错误地改变基类来容纳其中一个孩子。

我一直认为基类应该什么都不知道
$他们孩子的b $ b,继承的唯一目的是扩展

基类。我没有充分的理由说明为什么这是一个糟糕的实现(如果它甚至是一个糟糕的实现)。任何想法

都会很棒。

I tried for an hour to find some reference to concrete information on
why this particular inheritance implementation is a bad idea, but
couldn''t. So I''m sorry if this has been answered before. Here''s the
scenario:

We have a base class with all virtual functions. We''ll call this the
Animal class. We then make two classes Fish and Bird that both inherit
from Animal. In the program, we have a single array of Animal pointers
that will house all of the Fish and Bird objects . For the most part,
they share functions (Eat, Breathe, etc.), so you would be able to just
call AnimalArray[i]->Eat() and it is handled polymorphically. Here is
my problem, let''s say that you want to add a RuffleFeathers function to
the Bird class. Now in order to still call
AnimalArray[i]->RuffleFeathers(), I would have to add that function
definition to the Animal class, even though not all animals will have
feathers. So I just put a vitual function declaration and a stub with
a return statement in the Animal class, so if I call
AnimalArray[i]->RuffleFeathers() on a Fish object, it will just execute
the stub defined in Animal. To me, it just feels wrong to do it that
way.

Here''s what the code would look like:

class Animal {

virtual void Eat() {return;}
virtual void RuffleFeathers() {return;}
};
class Bird : public Animal {

void Eat() {printf("Eat a mouse.");}
void RuffleFeathers {printf("Feathers ruffled.")};
};
class Fish : public Animal {

void Eat() {printf("Eat some kelp.");}
};
int main()
{
Animal* animalArray = new Animal[100];
animalArray[0] = new Fish();
animalArray[1] = new Bird();

animalArray[0]->Eat();
}

Now take this small example and extend it to 10 classes that inherit
from Animal with about 6 or so functions, like RuffleFeathers, that
have nothing to do with any of the other inherited classes. The thing
is that the implementation works, and you don''t have to do a type check
or cast on each element in the single array before calling a function.
Nor do you have to keep multiple arrays of each type. But it just
seems wrong to change the base class to accomidate one of the children.
I have been under the impression that base classes should know nothing
of their children, and the sole purpose of inheritance was to extend
base classes. I just have no solid reason why this is a bad
implementation (if it even is a bad implementation). Any thoughts
would be great.

推荐答案

bs **** @ gmail.com 写道:
bs****@gmail.com wrote:

我们有一个包含所有虚函数的基类。我们称之为

Animal类。然后我们制作了两个类Fish和Bird,它们都继承了动物的
。在程序中,我们有一个动物指针数组

将容纳所有鱼和鸟对象。在大多数情况下,

他们共享功能(吃,呼吸等),所以你可以只用

来调用AnimalArray [i] - > Eat(并且它以多态方式处理。这是

我的问题,让我们说你想把一个RuffleFeathers函数添加到Bird类的
。现在为了仍然调用

AnimalArray [i] - > RuffleFeathers(),我必须添加该函数
We have a base class with all virtual functions. We''ll call this the
Animal class. We then make two classes Fish and Bird that both inherit
from Animal. In the program, we have a single array of Animal pointers
that will house all of the Fish and Bird objects . For the most part,
they share functions (Eat, Breathe, etc.), so you would be able to just
call AnimalArray[i]->Eat() and it is handled polymorphically. Here is
my problem, let''s say that you want to add a RuffleFeathers function to
the Bird class. Now in order to still call
AnimalArray[i]->RuffleFeathers(), I would have to add that function



这个问题可以是:为什么你可能想这样做?那就是:你真的好吗?b $ b想要一个可以被描述为可以惹恼动物的动物的容器b $ b羽毛?如果没有,执行此代码没有意义,恕我直言。


也许你需要一个更通用的概念和功能名称,以回应

哪些鸟叫RuffleFeathers和其他动物做其他事情(或

什么都没有)。


-

Salu2

The question can be: why you may want to do that? That is: did you really
want a container that can be described as "Animals that can ruffle
feathers"? If not, execute this code does not make sense, IMHO.

Maybe you need a more generic concept and function name, in response to
which the birds call RuffleFeathers and other animal do other things (or
nothing).

--
Salu2



bs****@gmail.com 写道:

我们有一个包含所有虚函数的基类。我们称之为

Animal类。然后我们制作了两个类Fish和Bird,它们都继承了动物的
。在程序中,我们有一个动物指针数组

将容纳所有鱼和鸟对象。在大多数情况下,

他们共享功能(吃,呼吸等),所以你可以只用

来调用AnimalArray [i] - > Eat(并且它以多态方式处理。这是

我的问题,让我们说你想把一个RuffleFeathers函数添加到Bird类的
。现在为了仍然调用

AnimalArray [i] - > RuffleFeathers(),我必须将该函数

定义添加到Animal类中,即使不是全部动物将有b $ b b羽毛。所以我只是在Animal类中添加了一个虚函数声明和一个带有

a返回语句的存根,所以如果我调用

AnimalArray [i] - > RuffleFeathers()on一个Fish对象,它只会执行动物中定义的存根的
。对我来说,做到这一点只是感觉不对。

方式。
We have a base class with all virtual functions. We''ll call this the
Animal class. We then make two classes Fish and Bird that both inherit
from Animal. In the program, we have a single array of Animal pointers
that will house all of the Fish and Bird objects . For the most part,
they share functions (Eat, Breathe, etc.), so you would be able to just
call AnimalArray[i]->Eat() and it is handled polymorphically. Here is
my problem, let''s say that you want to add a RuffleFeathers function to
the Bird class. Now in order to still call
AnimalArray[i]->RuffleFeathers(), I would have to add that function
definition to the Animal class, even though not all animals will have
feathers. So I just put a vitual function declaration and a stub with
a return statement in the Animal class, so if I call
AnimalArray[i]->RuffleFeathers() on a Fish object, it will just execute
the stub defined in Animal. To me, it just feels wrong to do it that
way.



我想说这是一个非常常见的问题,可以用任何

面向类的语言出现。我不认为Animal应该有一个

RuffleFeathers方法,因为Animal是一个接口。并且应该只有

具有与所有派生类共享/共同的方法,就像你说的那样。你可以为这个类型添加一个额外的枚举数据成员(带有相应的虚拟

getType())并进行类型检查+向下转换来调用

只在Bird类中的方法。另一个解决方案是使用DoExtraAction(const char * action)= 0来概括你想要的派生类

中的附加功能。在基类中。然后

你最终会做类似

a-> DoExtraAction(" RuffleFeathers");鸟类以有意义的方式处理那个

参数(当然它不一定是char *,

'这只是一个死的简单例子。)这种方式并不比将RuffleFeathers添加到基础更好,因为你仍然可以通过逻辑无用的函数调用来结束
。另一种方法是

将额外的动作分离到另一个界面......有很多方法可以实现类似的结果,而且我认为没有一个&最好的方式为了解决这个问题,所有人都有起伏不定的问题。就我个人而言,
可能会在派生类中使用一些简单的类型数据

在基类中使用getType()并在

需要调用专门的方法。它避免了使用可能与派生类无关的方法污染界面



关于在AfricanElephant对象上调用RuffleFeathers()的事情

听起来不对,即使它是虚拟调用空的

方法;)

I would say this is a very common issue to come up in any
class-oriented language. I don''t think Animal should have a
RuffleFeathers method because Animal is an "interface" and should only
have methods shared/common with all derived classes, like you said. You
could add an extra enum data member (with a corresponding virtual
getType() maybe) for the type and do a type-check + downcast to call
the method that is only in the Bird class. Another solution would be to
generalize the additional functionality you want in derived classes
with a DoExtraAction( const char* action ) = 0; in the base class. Then
you would end up doing something like
a->DoExtraAction("RuffleFeathers"); where the bird class handled that
argument in a meaningful way (of course it doesn''t have to be char*,
that''s just a dead simple example.) That way isn''t really that much
better than adding the RuffleFeathers to the base because you still end
up with logically useless function calls. Another way would be to
decouple extra actions to another interface... There are many ways to
achieve similar results, and I don''t think there is a "best way" to
tackle this problem, there''s ups and downs to all of them. Personally I
would probably go with some simple type data in the derived classes
with a getType() in the base class and cast to the proper type when you
need to call specialized methods. It avoids polluting the interface
with methods that might have NOTHING to do with derived classes.
Something about calling RuffleFeathers() on an AfricanElephant object
just doesn''t sound right, even if it''s a virtual call to an empty
method ;)



bs****@gmail.com 写道:

bs****@gmail.com wrote:

我试了一个小时,找到一些关于

的具体信息的参考,为什么这个特殊的继承实现是一个坏主意,但是

不能。如果以前已经回答过这个问题我很抱歉。这是

场景:


我们有一个包含所有虚函数的基类。我们称之为

Animal类。然后我们制作了两个类Fish和Bird,它们都继承了动物的
。在程序中,我们有一个动物指针数组

将容纳所有鱼和鸟对象。在大多数情况下,

他们共享功能(吃,呼吸等),所以你可以只用

来调用AnimalArray [i] - > Eat(并且它以多态方式处理。这是

我的问题,让我们说你想把一个RuffleFeathers函数添加到Bird类的
。现在为了仍然调用

AnimalArray [i] - > RuffleFeathers(),我必须将该函数

定义添加到Animal类中,即使不是全部动物将有b $ b b羽毛。所以我只是在Animal类中添加了一个虚函数声明和一个带有

a返回语句的存根,所以如果我调用

AnimalArray [i] - > RuffleFeathers()on一个Fish对象,它只会执行动物中定义的存根的
。对我来说,这样做是错误的。

方式。


这就是代码的样子:


class Animal {


virtual void Eat(){return;}

virtual void RuffleFeathers(){return;}

};


class Bird:public Animal {


void Eat(){printf("吃一只老鼠。 ");}

void RuffleFeathers {printf(" Feathers ruffled。")};

};


class Fish:公共动物{


void Eat(){printf(吃一些海带。);}

};


int main()

{

动物* animalArray =新动物[100];

animalArray [0 ] = new Fish();

animalArray [1] = new Bird();


animalArray [0] - > Eat();

}


现在把这个小例子扩展到10个类,这些类从Animal继承

,大约有6个左右的函数,比如RuffleFeathers,

什么都没有与任何其他继承的类有关。事情

是实现工作,你不必在调用函数之前对单个数组中的每个元素进行类型检查

或强制转换。

你也不必保留每种类型的多个数组。但它只是

似乎错误地改变基类来容纳其中一个孩子。
I tried for an hour to find some reference to concrete information on
why this particular inheritance implementation is a bad idea, but
couldn''t. So I''m sorry if this has been answered before. Here''s the
scenario:

We have a base class with all virtual functions. We''ll call this the
Animal class. We then make two classes Fish and Bird that both inherit
from Animal. In the program, we have a single array of Animal pointers
that will house all of the Fish and Bird objects . For the most part,
they share functions (Eat, Breathe, etc.), so you would be able to just
call AnimalArray[i]->Eat() and it is handled polymorphically. Here is
my problem, let''s say that you want to add a RuffleFeathers function to
the Bird class. Now in order to still call
AnimalArray[i]->RuffleFeathers(), I would have to add that function
definition to the Animal class, even though not all animals will have
feathers. So I just put a vitual function declaration and a stub with
a return statement in the Animal class, so if I call
AnimalArray[i]->RuffleFeathers() on a Fish object, it will just execute
the stub defined in Animal. To me, it just feels wrong to do it that
way.

Here''s what the code would look like:

class Animal {

virtual void Eat() {return;}
virtual void RuffleFeathers() {return;}
};
class Bird : public Animal {

void Eat() {printf("Eat a mouse.");}
void RuffleFeathers {printf("Feathers ruffled.")};
};
class Fish : public Animal {

void Eat() {printf("Eat some kelp.");}
};
int main()
{
Animal* animalArray = new Animal[100];
animalArray[0] = new Fish();
animalArray[1] = new Bird();

animalArray[0]->Eat();
}

Now take this small example and extend it to 10 classes that inherit
from Animal with about 6 or so functions, like RuffleFeathers, that
have nothing to do with any of the other inherited classes. The thing
is that the implementation works, and you don''t have to do a type check
or cast on each element in the single array before calling a function.
Nor do you have to keep multiple arrays of each type. But it just
seems wrong to change the base class to accomidate one of the children.


我的印象是基类不应该知道他们孩子的
,以及继承的唯一目的是扩展

基类。我没有充分的理由说明为什么这是一个糟糕的实现(如果它甚至是一个糟糕的实现)。任何想法

都会很棒。
I have been under the impression that base classes should know nothing
of their children, and the sole purpose of inheritance was to extend
base classes. I just have no solid reason why this is a bad
implementation (if it even is a bad implementation). Any thoughts
would be great.



如果没有上下文,我们无法为您提供全球定义良好的解决方案

,因为没有。但根据我的经验,污染基类是不明智的。 基础班应该对他们的孩子一无所知。很好。

但是继承的唯一目的是扩展基类。不是这个案子的b $ b。我们有许多目的可以继承。在您的情况下,您将
定义为基类作为接口。因此你继承了

实现不扩展的接口。因此,如果你想在界面中添加一些

而不是实现,你应该加倍

检查你的设计。


也许你不需要这样的接口,基类仅用于代码

重用。所以你最好不要使用基本数组。或许你可以改变

Ruffle到其他更通用的界面。


最糟糕的方法是使用dynamic_cast而不是污染界面。

Without the context, we cannot give you a global well defined solution
because there is not one. But on my experience polluting base class is
not wise. "Base classes should know nothing of their children" is good.
But "the sole purpose of inheritance was to extend base classes" is not
the case. There are many purposes for us to inherit. In your case, you
define the base class as an interface. Therefore you inherit to
implement the interface not to extend. So if you want to add something
not in the interface and not for implementation, you should double
check your design.

Maybe you don''t need such an interface, the base class is just for code
reuse. So you''d better not use a base array. Or maybe you can change
Ruffle to other more general interface.

The worst way is to use dynamic_cast rather than pollute the interface.


这篇关于继承实现只是感觉不对,我需要理由......的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆