现有2个子类X,Y都从A派生,请问X中再包含Y可不可以?有什么优缺点?
class A { }
class X : public A;
class Y : publc A;
class X
{
private: Y y;
...
}
37 个解决方案
#1
当然可以,它们是包含关系,没有冲突,但觉得内容已经重叠
#2
从语法上说可以。
但是真要这么做,最好用指针,而且是基类指针。
但是真要这么做,最好用指针,而且是基类指针。
#3
为什么非要那么做?
class A { }
class X ;
class Y ;
class X: public A {...}
class A { }
class X ;
class Y ;
class X: public A {...}
#4
语法上是没有问题的,但这样使用的话,X中等于有了两个A的拷贝。
造成重复。
造成重复。
#5
语法上没有错,并不代表设计上没问题
编程中语法是次要的,只要编译通过就行,设计才是最重要的
设计越好,越容易实现,写代码越容易且不易出错
编程中语法是次要的,只要编译通过就行,设计才是最重要的
设计越好,越容易实现,写代码越容易且不易出错
#6
多谢大家。我也是这么考虑的。
原因是我想把最基础的类设计成一个窗口物体,包含最基本的句柄,id,和座标,都是protected。
然后这样其他所有的类都是继承而来,但有的物体(城市),我想也让它包含其他物体(到其他城市的路径),
这些路径也都是一个个小的物体,我想让他们属于各自的城市,这样搜索起来方便。
这样就有问题了:
如果把这个路径设计成一个新类,它又要重新写最基本的句柄,id,和座标,也不是很爽。大家有什么建议?
原因是我想把最基础的类设计成一个窗口物体,包含最基本的句柄,id,和座标,都是protected。
然后这样其他所有的类都是继承而来,但有的物体(城市),我想也让它包含其他物体(到其他城市的路径),
这些路径也都是一个个小的物体,我想让他们属于各自的城市,这样搜索起来方便。
这样就有问题了:
如果把这个路径设计成一个新类,它又要重新写最基本的句柄,id,和座标,也不是很爽。大家有什么建议?
#7
需要三个类吗?
class x{
};
class y: public x{
private:
y *abut;//邻接的城市,用链表实现,在构造函数中初始化为NULL,写专门的函数增加城市.
};
#8
把它们以树的形式组织起来
#9
感觉没什么意思 怎么写 不提倡啊
#10
不提倡,其中一个子类多了一份冗余数据
#11
城市必须作为窗口显示出来,路径中的各个点也必须作为窗口显示。
#12
按照6楼的观点,这样设计没有问题。
#13
class x{
};
class y: public x{
private:
y *abut;//邻接的城市,用链表实现,在构造函数中初始化为NULL,写专门的函数增加城市.
};
X是窗口,Y在X上派生不就可以用窗口显示了吗?而邻接的城市是指针类型,你添加的时候NEW出来不也是窗口吗?
#14
理论上是可以的,但是就是有点不太符合大家的习惯而已
#15
up
#16
城市是个窗口,呵呵有意思。
#17
可能老兄没有理解我的问题: 我的邻接的城市其实就是这么实现的。
关键是路径,一个个路径点是包含在城市里的一个非类成员呢?还是作为一个
单独的class呢(因为也是窗口,就打算继承A类)?
我这两天找了几本书来看,看到The C++ Programming Language Bjarne_Stroustrup上有句话:
"不要从具体的类继承。" 经典!!!而且正好那我这样的反例来说明会产生一个逻辑的回圈,导致各个类关系混乱。
所以我打算改成:不用继承。最小的通用窗口是个具体的类(就是上面的A),其他的城市包含这个类。
#18
按lz的需求,这么设计没什么问题
就像CDialog和CEdit等控件类都是继承自CWnd,我也经常在CDialog里面有CEdit成员,有时也用指针,看你个人爱好了,用成员的时候实例化时自动会分配空间,用指针则自行分配空间实例化。
不过如果按lz的设计这些实例如果都是独立的话,最好用指针;如果非独立的,比如某个城市内“绑定”有某些路径的话,则直接用类对象成员即可,安全且方便。
就像CDialog和CEdit等控件类都是继承自CWnd,我也经常在CDialog里面有CEdit成员,有时也用指针,看你个人爱好了,用成员的时候实例化时自动会分配空间,用指针则自行分配空间实例化。
不过如果按lz的设计这些实例如果都是独立的话,最好用指针;如果非独立的,比如某个城市内“绑定”有某些路径的话,则直接用类对象成员即可,安全且方便。
#19
嗯,比原来的好。。。
但不能骄傲喔,想想有没有更好的^_^
但不能骄傲喔,想想有没有更好的^_^
#20
哈哈哈哈哈哈,新年快乐。
我其实一直也在想这个问题,肯定还要某些设计类的知识。唉,突然发现:陪伴了我4年的C/C++,我对它其实一无所知。
#21
可以
#22
老兄一眼就看出我想绑定路径,牛!
不过如开始所说,基类就是简单的hwnd,id,都是protected,城市和路径都是继承而来,城市中如果包含路径实例,这样城市的class中的hwnd,id栏位会和路径的hwnd,id栏位重复吧?会不会有些乱?
#23
最好别这样
#24
每个类是一个命名域,不同域内的变量名重复没关系,当然你自己要分清楚,比如ID:
class A {
public:
A(int id):ID(id){};
int getID(){return ID;}
protected:
int ID;
};
class Y: public A
{
public:
Y(int id):A(id){}
};
class X: public A
{
private:
Y y;
public:
X(int id,int id_y):A(id),y(id_y){}
int getYID(){return y.getID();}
};
X对象只能用getID来获取自己的ID,而用getYID()来获取成员y的ID
#25
看看设计模式吧
能写一个类不是问题
能写出很多类,而且要把类写好,结合好,还是要看看设计模式的
你的x,y类都是从a继承,同时x里面有组合了y,问题倒是没有问题,类的耦合和类的重叠就让整个类的设计显得很不好了
#26
为了避免相互包含等副作用,最好用指针
class obj
{
};
class path : public obj
{
};
class city : public obj
{
public :
vector<path*> vPaths;
};
#27
我也就是想这么写,吼吼。不过好像指针的副作用更大。
变量名不是问题。
class A {
protected: ID;
...};
关键就是这个ID栏位。X里面有,Y里面也有。
所以让X里面包含Y,总感觉在X里面重复冗余定义了一个ID栏位,总感不爽,
就如同前面几位仁兄和ztz0223回复的那样:
除非把继承看做是为了定义一个新类而避免敲相同的代码:
就是除非上面的代码完全等同于:
-没有 class A
-class Y { private: ID; ...};
-class X { private: ID; Y y; ...};
变量名不是问题。
class A {
protected: ID;
...};
关键就是这个ID栏位。X里面有,Y里面也有。
所以让X里面包含Y,总感觉在X里面重复冗余定义了一个ID栏位,总感不爽,
就如同前面几位仁兄和ztz0223回复的那样:
除非把继承看做是为了定义一个新类而避免敲相同的代码:
就是除非上面的代码完全等同于:
-没有 class A
-class Y { private: ID; ...};
-class X { private: ID; Y y; ...};
#28
这个ID是其成员的ID,何为重复呢?每个对象的ID只有一个,这种设计方法每个X对象总有着自己“独占”的Y对象,何况你的Y是private,也就是说不可能会重复。
我觉得这种思路下的设计就算是用指针也要在X实例化时在构造函数里分配空间实例化成员,还不如直接用类对象做成员更加方便且安全。除非你的Y并不是“绑定”的,比如不是private;不是在X实例化时就固定下来的(需要动态生成);生命周期不是伴随着X对象。
#29
那继承就是为了定义一个新类而避免敲相同的代码了吗?:
上面继承A的代码完全等同于:
-没有 class A
-class Y { private: ID; ...};
-class X { private: ID; Y y; ...};
#30
-class A { protected: int ID; };
-class X : public A {};
-class Y { protected: A a; };
如果构造两个class , X和Y有什么不同?好像一样吧?
#31
哦,不一样。
-class A { protected: int ID; };
-class X : public A {};
但可以说X就是A吗?就是定义了两个完全相同的类,只是名称不同。
-class A { protected: int ID; };
-class X : public A {};
但可以说X就是A吗?就是定义了两个完全相同的类,只是名称不同。
#32
继承是为了“特例化”呀,你的X和Y总会有些跟别人不同的东西吧,拿你的例子来说:
城市X总有城市名、邮编、所处省、人口数等等
街道Y总会有街道名、长度、方位、区域等
基类是为了提取出“共同”的东西,继承类是为了体现“特殊”的东西,你要是X和Y都一样何必要两个类。。跟A一样何必要继承。。
城市X总有城市名、邮编、所处省、人口数等等
街道Y总会有街道名、长度、方位、区域等
基类是为了提取出“共同”的东西,继承类是为了体现“特殊”的东西,你要是X和Y都一样何必要两个类。。跟A一样何必要继承。。
#33
多谢了。
我举这个特殊的例子其实还是理解我原来那个疑问,子类中包含另一个子类,我也像前面几位回答我的网友一样的认为不妥。
原因是:
Y继承A,有了“共同”的东西;(可以表示为:Y是一个大框,套在里面的是小框A)
X继承A,有了“共同”的东西;(可以表示为:X是一个大框,套在里面的是小框A)
然后X再包含Y,怎么表示这个X类呢?(不是说一个object的实现,而只是问怎么表示这个class?)
(应该表示为:大框X里面有一个“共同”部份和一个次大框Y,Y里面还有一个“共同”部份。)
这也就是我们所说的X里面有两个“共同”部份。
我举这个特殊的例子其实还是理解我原来那个疑问,子类中包含另一个子类,我也像前面几位回答我的网友一样的认为不妥。
原因是:
Y继承A,有了“共同”的东西;(可以表示为:Y是一个大框,套在里面的是小框A)
X继承A,有了“共同”的东西;(可以表示为:X是一个大框,套在里面的是小框A)
然后X再包含Y,怎么表示这个X类呢?(不是说一个object的实现,而只是问怎么表示这个class?)
(应该表示为:大框X里面有一个“共同”部份和一个次大框Y,Y里面还有一个“共同”部份。)
这也就是我们所说的X里面有两个“共同”部份。
#34
这个"共同"的东西只是从数据的角度来说的,具体到继承类可就不是“共同”的了,会被“特殊”化的(内容)
就拿你所说的hwnd和iD来说,X有,Y有,X包含Y,则X中有“双份”,但这双份是“重复”的么?X需要,Y需要,可以单份么?
关键是你包含了Y,到底Y是不是不需要“这份”?如果需要,何来重复?
#35
不止要考虑编译,重在设计
#36
吼吼,早上醒来,我也突然想通了这个道理!真是的,何来重复?!
看来结论可以下了:如果需要,子类可以包含另一个子类。
多谢老兄不厌其烦,送200分,表个心意,以后还应会请教。
并多谢大家了。新年快乐。
#37
晕,每帖只能加分一次,此帖已加过分,不能再加了。
吼吼,wiowei兄,俺欠你一百分。
吼吼,wiowei兄,俺欠你一百分。
#1
当然可以,它们是包含关系,没有冲突,但觉得内容已经重叠
#2
从语法上说可以。
但是真要这么做,最好用指针,而且是基类指针。
但是真要这么做,最好用指针,而且是基类指针。
#3
为什么非要那么做?
class A { }
class X ;
class Y ;
class X: public A {...}
class A { }
class X ;
class Y ;
class X: public A {...}
#4
语法上是没有问题的,但这样使用的话,X中等于有了两个A的拷贝。
造成重复。
造成重复。
#5
语法上没有错,并不代表设计上没问题
编程中语法是次要的,只要编译通过就行,设计才是最重要的
设计越好,越容易实现,写代码越容易且不易出错
编程中语法是次要的,只要编译通过就行,设计才是最重要的
设计越好,越容易实现,写代码越容易且不易出错
#6
多谢大家。我也是这么考虑的。
原因是我想把最基础的类设计成一个窗口物体,包含最基本的句柄,id,和座标,都是protected。
然后这样其他所有的类都是继承而来,但有的物体(城市),我想也让它包含其他物体(到其他城市的路径),
这些路径也都是一个个小的物体,我想让他们属于各自的城市,这样搜索起来方便。
这样就有问题了:
如果把这个路径设计成一个新类,它又要重新写最基本的句柄,id,和座标,也不是很爽。大家有什么建议?
原因是我想把最基础的类设计成一个窗口物体,包含最基本的句柄,id,和座标,都是protected。
然后这样其他所有的类都是继承而来,但有的物体(城市),我想也让它包含其他物体(到其他城市的路径),
这些路径也都是一个个小的物体,我想让他们属于各自的城市,这样搜索起来方便。
这样就有问题了:
如果把这个路径设计成一个新类,它又要重新写最基本的句柄,id,和座标,也不是很爽。大家有什么建议?
#7
需要三个类吗?
class x{
};
class y: public x{
private:
y *abut;//邻接的城市,用链表实现,在构造函数中初始化为NULL,写专门的函数增加城市.
};
#8
把它们以树的形式组织起来
#9
感觉没什么意思 怎么写 不提倡啊
#10
不提倡,其中一个子类多了一份冗余数据
#11
城市必须作为窗口显示出来,路径中的各个点也必须作为窗口显示。
#12
按照6楼的观点,这样设计没有问题。
#13
class x{
};
class y: public x{
private:
y *abut;//邻接的城市,用链表实现,在构造函数中初始化为NULL,写专门的函数增加城市.
};
X是窗口,Y在X上派生不就可以用窗口显示了吗?而邻接的城市是指针类型,你添加的时候NEW出来不也是窗口吗?
#14
理论上是可以的,但是就是有点不太符合大家的习惯而已
#15
up
#16
城市是个窗口,呵呵有意思。
#17
可能老兄没有理解我的问题: 我的邻接的城市其实就是这么实现的。
关键是路径,一个个路径点是包含在城市里的一个非类成员呢?还是作为一个
单独的class呢(因为也是窗口,就打算继承A类)?
我这两天找了几本书来看,看到The C++ Programming Language Bjarne_Stroustrup上有句话:
"不要从具体的类继承。" 经典!!!而且正好那我这样的反例来说明会产生一个逻辑的回圈,导致各个类关系混乱。
所以我打算改成:不用继承。最小的通用窗口是个具体的类(就是上面的A),其他的城市包含这个类。
#18
按lz的需求,这么设计没什么问题
就像CDialog和CEdit等控件类都是继承自CWnd,我也经常在CDialog里面有CEdit成员,有时也用指针,看你个人爱好了,用成员的时候实例化时自动会分配空间,用指针则自行分配空间实例化。
不过如果按lz的设计这些实例如果都是独立的话,最好用指针;如果非独立的,比如某个城市内“绑定”有某些路径的话,则直接用类对象成员即可,安全且方便。
就像CDialog和CEdit等控件类都是继承自CWnd,我也经常在CDialog里面有CEdit成员,有时也用指针,看你个人爱好了,用成员的时候实例化时自动会分配空间,用指针则自行分配空间实例化。
不过如果按lz的设计这些实例如果都是独立的话,最好用指针;如果非独立的,比如某个城市内“绑定”有某些路径的话,则直接用类对象成员即可,安全且方便。
#19
嗯,比原来的好。。。
但不能骄傲喔,想想有没有更好的^_^
但不能骄傲喔,想想有没有更好的^_^
#20
哈哈哈哈哈哈,新年快乐。
我其实一直也在想这个问题,肯定还要某些设计类的知识。唉,突然发现:陪伴了我4年的C/C++,我对它其实一无所知。
#21
可以
#22
老兄一眼就看出我想绑定路径,牛!
不过如开始所说,基类就是简单的hwnd,id,都是protected,城市和路径都是继承而来,城市中如果包含路径实例,这样城市的class中的hwnd,id栏位会和路径的hwnd,id栏位重复吧?会不会有些乱?
#23
最好别这样
#24
每个类是一个命名域,不同域内的变量名重复没关系,当然你自己要分清楚,比如ID:
class A {
public:
A(int id):ID(id){};
int getID(){return ID;}
protected:
int ID;
};
class Y: public A
{
public:
Y(int id):A(id){}
};
class X: public A
{
private:
Y y;
public:
X(int id,int id_y):A(id),y(id_y){}
int getYID(){return y.getID();}
};
X对象只能用getID来获取自己的ID,而用getYID()来获取成员y的ID
#25
看看设计模式吧
能写一个类不是问题
能写出很多类,而且要把类写好,结合好,还是要看看设计模式的
你的x,y类都是从a继承,同时x里面有组合了y,问题倒是没有问题,类的耦合和类的重叠就让整个类的设计显得很不好了
#26
为了避免相互包含等副作用,最好用指针
class obj
{
};
class path : public obj
{
};
class city : public obj
{
public :
vector<path*> vPaths;
};
#27
我也就是想这么写,吼吼。不过好像指针的副作用更大。
变量名不是问题。
class A {
protected: ID;
...};
关键就是这个ID栏位。X里面有,Y里面也有。
所以让X里面包含Y,总感觉在X里面重复冗余定义了一个ID栏位,总感不爽,
就如同前面几位仁兄和ztz0223回复的那样:
除非把继承看做是为了定义一个新类而避免敲相同的代码:
就是除非上面的代码完全等同于:
-没有 class A
-class Y { private: ID; ...};
-class X { private: ID; Y y; ...};
变量名不是问题。
class A {
protected: ID;
...};
关键就是这个ID栏位。X里面有,Y里面也有。
所以让X里面包含Y,总感觉在X里面重复冗余定义了一个ID栏位,总感不爽,
就如同前面几位仁兄和ztz0223回复的那样:
除非把继承看做是为了定义一个新类而避免敲相同的代码:
就是除非上面的代码完全等同于:
-没有 class A
-class Y { private: ID; ...};
-class X { private: ID; Y y; ...};
#28
这个ID是其成员的ID,何为重复呢?每个对象的ID只有一个,这种设计方法每个X对象总有着自己“独占”的Y对象,何况你的Y是private,也就是说不可能会重复。
我觉得这种思路下的设计就算是用指针也要在X实例化时在构造函数里分配空间实例化成员,还不如直接用类对象做成员更加方便且安全。除非你的Y并不是“绑定”的,比如不是private;不是在X实例化时就固定下来的(需要动态生成);生命周期不是伴随着X对象。
#29
那继承就是为了定义一个新类而避免敲相同的代码了吗?:
上面继承A的代码完全等同于:
-没有 class A
-class Y { private: ID; ...};
-class X { private: ID; Y y; ...};
#30
-class A { protected: int ID; };
-class X : public A {};
-class Y { protected: A a; };
如果构造两个class , X和Y有什么不同?好像一样吧?
#31
哦,不一样。
-class A { protected: int ID; };
-class X : public A {};
但可以说X就是A吗?就是定义了两个完全相同的类,只是名称不同。
-class A { protected: int ID; };
-class X : public A {};
但可以说X就是A吗?就是定义了两个完全相同的类,只是名称不同。
#32
继承是为了“特例化”呀,你的X和Y总会有些跟别人不同的东西吧,拿你的例子来说:
城市X总有城市名、邮编、所处省、人口数等等
街道Y总会有街道名、长度、方位、区域等
基类是为了提取出“共同”的东西,继承类是为了体现“特殊”的东西,你要是X和Y都一样何必要两个类。。跟A一样何必要继承。。
城市X总有城市名、邮编、所处省、人口数等等
街道Y总会有街道名、长度、方位、区域等
基类是为了提取出“共同”的东西,继承类是为了体现“特殊”的东西,你要是X和Y都一样何必要两个类。。跟A一样何必要继承。。
#33
多谢了。
我举这个特殊的例子其实还是理解我原来那个疑问,子类中包含另一个子类,我也像前面几位回答我的网友一样的认为不妥。
原因是:
Y继承A,有了“共同”的东西;(可以表示为:Y是一个大框,套在里面的是小框A)
X继承A,有了“共同”的东西;(可以表示为:X是一个大框,套在里面的是小框A)
然后X再包含Y,怎么表示这个X类呢?(不是说一个object的实现,而只是问怎么表示这个class?)
(应该表示为:大框X里面有一个“共同”部份和一个次大框Y,Y里面还有一个“共同”部份。)
这也就是我们所说的X里面有两个“共同”部份。
我举这个特殊的例子其实还是理解我原来那个疑问,子类中包含另一个子类,我也像前面几位回答我的网友一样的认为不妥。
原因是:
Y继承A,有了“共同”的东西;(可以表示为:Y是一个大框,套在里面的是小框A)
X继承A,有了“共同”的东西;(可以表示为:X是一个大框,套在里面的是小框A)
然后X再包含Y,怎么表示这个X类呢?(不是说一个object的实现,而只是问怎么表示这个class?)
(应该表示为:大框X里面有一个“共同”部份和一个次大框Y,Y里面还有一个“共同”部份。)
这也就是我们所说的X里面有两个“共同”部份。
#34
这个"共同"的东西只是从数据的角度来说的,具体到继承类可就不是“共同”的了,会被“特殊”化的(内容)
就拿你所说的hwnd和iD来说,X有,Y有,X包含Y,则X中有“双份”,但这双份是“重复”的么?X需要,Y需要,可以单份么?
关键是你包含了Y,到底Y是不是不需要“这份”?如果需要,何来重复?
#35
不止要考虑编译,重在设计
#36
吼吼,早上醒来,我也突然想通了这个道理!真是的,何来重复?!
看来结论可以下了:如果需要,子类可以包含另一个子类。
多谢老兄不厌其烦,送200分,表个心意,以后还应会请教。
并多谢大家了。新年快乐。
#37
晕,每帖只能加分一次,此帖已加过分,不能再加了。
吼吼,wiowei兄,俺欠你一百分。
吼吼,wiowei兄,俺欠你一百分。