由买买提看人间百态

boards

本页内容为未名空间相应帖子的节选和存档,一周内的贴子最多显示50字,超过一周显示500字 访问原贴
Programming版 - 该怎么设计这个类?
相关主题
问个 C++到C的问题C++子类中调用父类指针的问题
C & C++ mixing question[合集] 问一个design pattern的问题
子类的copy constructor怎么写[合集] 关于vector存储value copy的一个问题
子类的assignment operator 怎么访问父类的private membertemplate 类的继承问题
还请教一个关于C++的问题帮我看一下python 多线程这样写对不对
dynamic_cast operator in C++老调重弹 virtual destructor
请问2个类的问题[合集] 基类函数已经是virtual了,为啥子类还要virtual啊?
C++虚方法问题子类的destructor被调用时,什么时候调用基类的destructor
相关话题的讨论汇总
话题: female话题: humanbeing话题: male话题: bangwith话题: 子类
进入Programming版参与讨论
1 (共1页)
y**b
发帖数: 10166
1
父类B,
子类D1,D2,D3,
子类有很多相同的操作,也有几个不同的操作,比如D1op, D2op, D3op.
现在有一个C类中包含了B类指针,来操作其三个子类的对象(混合出现),
也就是有这种情况:
B *pB,
pB->D1op
pB->D2op
pB->D3op
显然,编译通不过,因为B类并没有定义这些操作。
想了几个办法:
1. 在B类中用虚函数定义这些操作,三个子类分别覆盖,如果没有动作就为空。
但这带来一个问题:B类中接口太宽,本来三个子类各自不同的操作,结果
父类反而都得有;如果再添加个子类及不同操作,那B类又得添加接口。感觉
特别不合理,这叫什么问题?
2.使用RTTI和向下转换dynamic_cast,B类转换成不同子类,可是这个转换要
做很多检测,还不一定转换成功;倒是static_cast反而明确一些,也最简单
可行?
3.碰巧C类使用B类三个不同子类(每次只用一个子类)作为组成部分,可以使用
类模板,也就是说用B类三个不同子类作为模板形参来构造C类。这样C类其实
也形成了三个子类,分别对应B类的三个子类,但是失去了使用B类的便利。
还是这几种办法根本就不对?请指教,多谢。
A*******e
发帖数: 2419
2
操作接口都不一样,何必要从同一个基类继承?

【在 y**b 的大作中提到】
: 父类B,
: 子类D1,D2,D3,
: 子类有很多相同的操作,也有几个不同的操作,比如D1op, D2op, D3op.
: 现在有一个C类中包含了B类指针,来操作其三个子类的对象(混合出现),
: 也就是有这种情况:
: B *pB,
: pB->D1op
: pB->D2op
: pB->D3op
: 显然,编译通不过,因为B类并没有定义这些操作。

y**b
发帖数: 10166
3
嗯,我没说清楚,大部分操作接口都是相同的,就有几个不同。我只列了几个不同的,
改了。
p***o
发帖数: 1252
4
把不同的改成相同的。

【在 y**b 的大作中提到】
: 嗯,我没说清楚,大部分操作接口都是相同的,就有几个不同。我只列了几个不同的,
: 改了。

A*******e
发帖数: 2419
5
子类自有的方法根本不应该通过父类调用

【在 y**b 的大作中提到】
: 嗯,我没说清楚,大部分操作接口都是相同的,就有几个不同。我只列了几个不同的,
: 改了。

y**b
发帖数: 10166
6
也许是这个道理。
可是生成这些子类对象的时候,就是用的父类指针,这还是比较普遍的吧?那怎么调用
自有方法呢。

【在 A*******e 的大作中提到】
: 子类自有的方法根本不应该通过父类调用
A*******e
发帖数: 2419
7
建模有问题。可以想想该如何重新设计。

【在 y**b 的大作中提到】
: 也许是这个道理。
: 可是生成这些子类对象的时候,就是用的父类指针,这还是比较普遍的吧?那怎么调用
: 自有方法呢。

y**b
发帖数: 10166
8
想过这么做,可是发现:
1. 有两个个成员函数signature略有不同(形参个数),但这也不是问题,仍然可以把它
们写成一样的signature,只是某些参数对某些子类是不需要的。
2. 有几个成员函数名字(含有物理意义)不同,若改成相同,倒是可以实现,但子类的
个性有点混淆啊,而且父类接口偏宽?
感觉这个思路和向下static_cast比,那个更好呢?也不局限于我这个例子,就普遍性
而言呢?
多谢大家指点。

【在 p***o 的大作中提到】
: 把不同的改成相同的。
p***o
发帖数: 1252
9
你这属于没抽象好。
如果子类参数不同就不应该由父类*直接*管理,参数可以交给子类管理最好,
不行的话可以考虑把参数装到一个map里由父类传给子类。
父类能在同一个函数里调不同子类的不同函数那说明他们是有联系的,有联系
就可以抽象出共性来。

【在 y**b 的大作中提到】
: 想过这么做,可是发现:
: 1. 有两个个成员函数signature略有不同(形参个数),但这也不是问题,仍然可以把它
: 们写成一样的signature,只是某些参数对某些子类是不需要的。
: 2. 有几个成员函数名字(含有物理意义)不同,若改成相同,倒是可以实现,但子类的
: 个性有点混淆啊,而且父类接口偏宽?
: 感觉这个思路和向下static_cast比,那个更好呢?也不局限于我这个例子,就普遍性
: 而言呢?
: 多谢大家指点。

y**b
发帖数: 10166
10
我是这样想的:能抽象出共性的尽可能抽出来放在父类,但是具体的差别还是放在子类
,这个设计应该算正常的。
但是用到子类那些有具体差别(其实概念上还算很接近)的接口时,不应该通过父类指针
来操作。
比如有30个接口抽象到父类了,还有三五个属于子类不同的属性。那30个接口采用父类
指针(比如含有大量父类指针的一个链表)进行操作非常方便,就那三五个子类特有的接
口得通过子类指针来操作。
我的问题好像在于:生成子类对象的时候直接采用了父类指针,结果遇到子类特有属性
的时候就得向下转换。如果生成子类对象的时候全部采用子类指针,遇到共性的时候将
这些子类指针(或者其容器)传给父类指针,好像问题就解决了;代价就是在C类中多维
护几个子类指针的容器并把它们适当地传给父类指针的容器,但是不会遇到向下转换的
问题。好像这样才是合理的做法?
之所以出这个问题,是因为原来程序只有B类,后来将B类改成D1类,同时添加D2类,再
重写B类,也为以后添加D3,D4做些准备。C类里面就一直想着偷懒用原来代码不变,其
实稍微改改就更合理了。
相关主题
dynamic_cast operator in C++C++子类中调用父类指针的问题
请问2个类的问题[合集] 问一个design pattern的问题
C++虚方法问题[合集] 关于vector存储value copy的一个问题
进入Programming版参与讨论
y**b
发帖数: 10166
11
麻烦也再看看我后面补充的想法。

【在 A*******e 的大作中提到】
: 建模有问题。可以想想该如何重新设计。
O*******d
发帖数: 20343
12
父类不应该知道子类特有的功能。
m*********n
发帖数: 28
13
后面的补充想法是对的。给你个范例程序
struct SexOrgan {
};
struct Asshole : public SexOrgan {
};
struct Dick : public SexOrgan {
};
struct Pussy : public SexOrgan {
void Eat(Dick& dick) {
};
};
void B2B(Pussy& p0, Pussy& p1) {
}
struct HumanBeing {
virtual void BangWith(HumanBeing & that) {
// take off all clothes;
}
};
struct Female;
struct Male : public HumanBeing {
virtual void BangWith(HumanBeing& that) {
HumanBeing::BangWith(that);
Female* female = dynamic_cast (&that);
if (female) {
Fuck(female->ShowB());
} else {
throw std::runtime_error("female only.");
}
}
SexOrgan& ShowStuff() {
return dick;
}
void Fuck(Pussy& pussy) {
}
Dick dick;
};
struct Gay : public HumanBeing {
virtual void BangWith(HumanBeing& that) {
HumanBeing::BangWith(that);
Gay* gay = dynamic_cast (&that);
if (gay) {
FuckAssole(gay->Bonus());
gay->FuckAssole(Bonus());
} else {
throw std::runtime_error("No gay no sex.");
}
}
Asshole& Bonus() {
return asshole;
}
void FuckAssole(Asshole& asshole) {
}
Asshole asshole;
};
struct Female : public HumanBeing {
virtual void BangWith(HumanBeing& that) {
HumanBeing::BangWith(that);
Male* male = dynamic_cast (&that);
if (male) {
pussy->Eat(male->ShowStuff());
} else {
Female* female = dynamic_cast (&that);
if (Female) {
B2B(pussy, female->ShowB());
} else {
throw std::runtime_error("Fuck off u gay!");
}
}
}
virtual Pussy& ShowB() {
return pussy;
}
Pussy pussy;
};
struct SexLifeWithoutProblem {
void Enjoy() {
for (Male* m : males) {
for (Female* f : females) {
m->BangWith(*f);
}
}
}
void Disgusting() {
for (Gay* g : gays) {
for (Gay* g1 : gays) {
if (g != g1) {
g->BangWith(*g1);
} else {
// unless this gay has a really long one...
g->BangWith(*g);
}
}
}
}
std::vector males;
std::vector females;
std::vector gays;
};
struct SexLifeWithProblem {
void TryIt() {
for (HumanBeing* p : people) {
for (HumanBeing* p1 : people) {
// hmmmm.... have to deal with these annoying gays...
p->BangWith(*p1);
}
}
}
std::vector people;
};

【在 y**b 的大作中提到】
: 麻烦也再看看我后面补充的想法。
m*********n
发帖数: 28
14
SexLifeWithoutProblem 里面不同的子类放在不同的地方。做爱时候不会出现任何问题。
SexLifeWithProblem 里面不同的子类放在同一个地方做爱的时候就会有问题
:D

【在 y**b 的大作中提到】
: 麻烦也再看看我后面补充的想法。
c*********e
发帖数: 16335
15
HumanBeing 有3个子类:Male, Female, Gay。
你这个是用if...else把不同的子类分开,如果子类是Male,这么做;如果子类是Female,
这么做. 那么,如果再要加一个新的子类,Transgender,你的很多函数要重新写了,比
如下面这个BangWith()函数。况且,gay,可以是Male, or Female.
struct Female : public HumanBeing {
virtual void BangWith(HumanBeing& that) {
HumanBeing::BangWith(that);
Male* male = dynamic_cast (&that);
if (male) {
pussy->Eat(male->ShowStuff());
} else {
Female* female = dynamic_cast (&that);
if (Female) {
B2B(pussy, female->ShowB());
} else {
throw std::runtime_error("Fuck off u gay!");
}
}
}
。。。

【在 m*********n 的大作中提到】
: 后面的补充想法是对的。给你个范例程序
: struct SexOrgan {
: };
: struct Asshole : public SexOrgan {
: };
: struct Dick : public SexOrgan {
: };
: struct Pussy : public SexOrgan {
: void Eat(Dick& dick) {
: };

m*********n
发帖数: 28
16
这个就是运行时的不同处理了必须用dynamic_cast做。

Female,

【在 c*********e 的大作中提到】
: HumanBeing 有3个子类:Male, Female, Gay。
: 你这个是用if...else把不同的子类分开,如果子类是Male,这么做;如果子类是Female,
: 这么做. 那么,如果再要加一个新的子类,Transgender,你的很多函数要重新写了,比
: 如下面这个BangWith()函数。况且,gay,可以是Male, or Female.
: struct Female : public HumanBeing {
: virtual void BangWith(HumanBeing& that) {
: HumanBeing::BangWith(that);
: Male* male = dynamic_cast (&that);
: if (male) {
: pussy->Eat(male->ShowStuff());

s******y
发帖数: 416
17
如果函数的sig相同,建议使用函数指针。在父类里设置一个接口就好。

【在 y**b 的大作中提到】
: 父类B,
: 子类D1,D2,D3,
: 子类有很多相同的操作,也有几个不同的操作,比如D1op, D2op, D3op.
: 现在有一个C类中包含了B类指针,来操作其三个子类的对象(混合出现),
: 也就是有这种情况:
: B *pB,
: pB->D1op
: pB->D2op
: pB->D3op
: 显然,编译通不过,因为B类并没有定义这些操作。

c*********e
发帖数: 16335
18
能写个代码做例子吗?

【在 s******y 的大作中提到】
: 如果函数的sig相同,建议使用函数指针。在父类里设置一个接口就好。
b*******s
发帖数: 5216
L****8
发帖数: 3938
20
不要搞这么多继承

【在 y**b 的大作中提到】
: 父类B,
: 子类D1,D2,D3,
: 子类有很多相同的操作,也有几个不同的操作,比如D1op, D2op, D3op.
: 现在有一个C类中包含了B类指针,来操作其三个子类的对象(混合出现),
: 也就是有这种情况:
: B *pB,
: pB->D1op
: pB->D2op
: pB->D3op
: 显然,编译通不过,因为B类并没有定义这些操作。

相关主题
template 类的继承问题[合集] 基类函数已经是virtual了,为啥子类还要virtual啊?
帮我看一下python 多线程这样写对不对子类的destructor被调用时,什么时候调用基类的destructor
老调重弹 virtual destructorC++的exception大家常用吗?
进入Programming版参与讨论
p*****2
发帖数: 21240
21
用lambda很容易就解耦了吧?
y**b
发帖数: 10166
22
原来是典型的依赖倒置原则,父类不应该依赖于之类。

1. 在B类中用虚函数定义这些操作,三个子类分别覆盖,如果没有动作就为空。
但这带来一个问题:B类中接口太宽,本来三个子类各自不同的操作,结果
父类反而都得有;如果再添加个子类及不同操作,那B类又得添加接口。感觉
特别不合理,这叫什么问题?

【在 y**b 的大作中提到】
: 麻烦也再看看我后面补充的想法。
c*********e
发帖数: 16335
23
en,感觉精华在这
virtual void BangWith(HumanBeing& that) {
HumanBeing::BangWith(that);
Male* male = dynamic_cast (&that);
if (male) {
...
} else {
...


【在 m*********n 的大作中提到】
: 后面的补充想法是对的。给你个范例程序
: struct SexOrgan {
: };
: struct Asshole : public SexOrgan {
: };
: struct Dick : public SexOrgan {
: };
: struct Pussy : public SexOrgan {
: void Eat(Dick& dick) {
: };

g****t
发帖数: 31659
24
定义个interface,或者用其他的语法糖。
但你既然问了这个问题,多半会被这些乱七八糟的东西
弄的很烦。
不如直接用 函数指针 完整的文档
另外这跟语言有关
Python meta programming 可能可以直接加函数进去
g****t
发帖数: 31659
25
Python可以运行时直接往类里面加lambda
这可能是最糙快猛的办法了


: 用lambda很容易就解耦了吧?



【在 p*****2 的大作中提到】
: 用lambda很容易就解耦了吧?
L****8
发帖数: 3938
26
oop 继承 是个垃圾 多少年了 毒害人

【在 y**b 的大作中提到】
: 父类B,
: 子类D1,D2,D3,
: 子类有很多相同的操作,也有几个不同的操作,比如D1op, D2op, D3op.
: 现在有一个C类中包含了B类指针,来操作其三个子类的对象(混合出现),
: 也就是有这种情况:
: B *pB,
: pB->D1op
: pB->D2op
: pB->D3op
: 显然,编译通不过,因为B类并没有定义这些操作。

c*********e
发帖数: 16335
27
继承还是有用的,java,c#的编程方法是正确的。

【在 L****8 的大作中提到】
: oop 继承 是个垃圾 多少年了 毒害人
z*********n
发帖数: 1451
28
没有具体代码,不知道详情,但最简单的办法肯定是朝着统一不同Op的接口这个方向努
力,至少统一返回值?可用的工具包括模板,变长参数列表,或者lambda
如果你能统一函数接口,很有可能可以避免dynamic_cast这种反oop设计原则的语句。
如果可以,最好贴一段短的,精简的样例代码供大家参考。
1 (共1页)
进入Programming版参与讨论
相关主题
子类的destructor被调用时,什么时候调用基类的destructor还请教一个关于C++的问题
C++的exception大家常用吗?dynamic_cast operator in C++
C++ multiple inheritance problem请问2个类的问题
问两个关于Emacs的c++补全问题C++虚方法问题
问个 C++到C的问题C++子类中调用父类指针的问题
C & C++ mixing question[合集] 问一个design pattern的问题
子类的copy constructor怎么写[合集] 关于vector存储value copy的一个问题
子类的assignment operator 怎么访问父类的private membertemplate 类的继承问题
相关话题的讨论汇总
话题: female话题: humanbeing话题: male话题: bangwith话题: 子类