473,662 Members | 2,581 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Composition using references

I have an ABC with a protected member that is a reference to an object
of an ABC type:

class ABC
{
public:
virtual ~ABC() = 0;
protected:
AnotherABC& _member;
}

The idea is that my concrete classes will derive from ABC and set
_member in their initialization lists to the specific type of
AnotherABC that the particular class needs. However, this can't be done
as the constructors of the derived classes complain about there being
no default constructor for ABC.

Should I simply replace the reference with a const pointer, or should I
rethink this and save myself from a potentially nasty design flaw? Is
there a design pattern I could use here?

Dec 10 '05 #1
31 2894
an************* *@googlemail.co m wrote:
I have an ABC with a protected member that is a reference to an object
of an ABC type:

class ABC
{
public:
virtual ~ABC() = 0;
your destructor should be protected, not public.
protected:

your data member should be private, not protected.
AnotherABC& _member;
}
The idea is that my concrete classes will derive from ABC and set
_member in their initialization lists to the specific type of
AnotherABC that the particular class needs.
Can't do that. Instead, ABC needs a (protected) constructor that sets
member, and the derived class can call that constructor.
However, this can't be done
as the constructors of the derived classes complain about there being
no default constructor for ABC.
It won't if you follow the above advice.
Should I simply replace the reference with a const pointer, or should I
rethink this and save myself from a potentially nasty design flaw? Is
there a design pattern I could use here?


I've given you code below:

class Other;

class Base {
Other& other_; // this is private
protected:
virtual ~Base() = 0;
Base(Other& o) : other_(o) {}
};

Base::~Base() {}

class Derived : public Base {
public:
Derived(Other& o) : Base(o) {}
};

Best regards,

Tom

Dec 10 '05 #2

Thomas Tutone wrote:
an************* *@googlemail.co m wrote:
I have an ABC with a protected member that is a reference to an object
of an ABC type:

class ABC
{
public:
virtual ~ABC() = 0;
your destructor should be protected, not public.


Why is that? I can understand the constructor being protected, but not
the destructor. Won't this mean that delete won't be able to call the
destructors of inherited classes through the ABC interface?
protected:

your data member should be private, not protected.
AnotherABC& _member;
}


Why? Must I use access methods in my derived classes when one of the
main points of the ABC is to provide a generalized declaration for my
data members in the class hierarchy? Is it inadvisable to have
protected data at all?

The idea is that my concrete classes will derive from ABC and set
_member in their initialization lists to the specific type of
AnotherABC that the particular class needs.


Can't do that. Instead, ABC needs a (protected) constructor that sets
member, and the derived class can call that constructor.
However, this can't be done
as the constructors of the derived classes complain about there being
no default constructor for ABC.


It won't if you follow the above advice.
Should I simply replace the reference with a const pointer, or should I
rethink this and save myself from a potentially nasty design flaw? Is
there a design pattern I could use here?


I've given you code below:

class Other;

class Base {
Other& other_; // this is private
protected:
virtual ~Base() = 0;
Base(Other& o) : other_(o) {}
};

Base::~Base() {}

class Derived : public Base {
public:
Derived(Other& o) : Base(o) {}
};

Best regards,

Tom


Thanks for your help, Tom. I hope my questions don't seem too stupid.

Dec 10 '05 #3
On 10 Dec 2005 12:49:47 -0800, "an************ **@googlemail.c om"
<an************ **@googlemail.c om> wrote:
I have an ABC with a protected member that is a reference to an object
of an ABC type:

class ABC
{
public:
virtual ~ABC() = 0;
protected:
AnotherABC& _member;
You shouldn't use names with a leading underscore for anything (see
17.4.3.1.2 of the C++ standard).
}

The idea is that my concrete classes will derive from ABC and set
_member in their initialization lists to the specific type of
AnotherABC that the particular class needs. However, this can't be done
as the constructors of the derived classes complain about there being
no default constructor for ABC.

Should I simply replace the reference with a const pointer, or should I
rethink this and save myself from a potentially nasty design flaw? Is
there a design pattern I could use here?


What Thomas said ... however, if the member is to be derived from ABC,
you will probably want to store a reference to ABC and not AnotherABC,
relying on the interface defined in ABC for whatever you need to do
with it. As it is, you cannot initialize this member with an object of
type YetAnotherABC, for example, even if that class also derives from
ABC.

--
Bob Hairgrove
No**********@Ho me.com
Dec 10 '05 #4
an************* *@googlemail.co m wrote:
I have an ABC with a protected member that is a reference to an object
of an ABC type:

class ABC
{
public:
virtual ~ABC() = 0;
protected:
AnotherABC& _member;
}

The idea is that my concrete classes will derive from ABC and set
_member in their initialization lists to the specific type of
AnotherABC that the particular class needs. However, this can't be done
as the constructors of the derived classes complain about there being
no default constructor for ABC.

Should I simply replace the reference with a const pointer, or should I
rethink this and save myself from a potentially nasty design flaw? Is
there a design pattern I could use here?


What's wrong with:

class AnotherABC;
class ABC
{
public:
virtual ~ABC() = 0;
protected:
ABC(AnotherABC& param) : _member(param) { }
AnotherABC& _member;
};
Dec 10 '05 #5

an************* *@googlemail.co m wrote:
Thomas Tutone wrote:
an************* *@googlemail.co m wrote:
I have an ABC with a protected member that is a reference to an object
of an ABC type:

class ABC
{
public:
virtual ~ABC() = 0;
your destructor should be protected, not public.


Why is that? I can understand the constructor being protected, but not
the destructor. Won't this mean that delete won't be able to call the
destructors of inherited classes through the ABC interface?


Perhaps you are missing the point. ABC's destructor will never be
called directly - because the destructor is virtual, it will be the
destructor of the derived class that will be called, which will in turn
call the base destructor. The derived destructor has access to the
protected functions of its parent.
protected:

your data member should be private, not protected.
AnotherABC& _member;
}
Why? Must I use access methods in my derived classes when one of the
main points of the ABC is to provide a generalized declaration for my
data members in the class hierarchy?


Typically, yes.
Is it inadvisable to have
protected data at all?
Typically yes. To quote Stroustrup: "declaring data members protected
is usually a design error." The C++ Programming Language (3rd ed.)
sec. 15.3.1.1

There are exceptions, but that's the usual rule. If your accessor is
inline, there is typically no overhead to using the accessor.

The idea is that my concrete classes will derive from ABC and set
_member in their initialization lists to the specific type of
AnotherABC that the particular class needs.
Can't do that. Instead, ABC needs a (protected) constructor that sets
member, and the derived class can call that constructor.
However, this can't be done
as the constructors of the derived classes complain about there being
no default constructor for ABC.


It won't if you follow the above advice.
Should I simply replace the reference with a const pointer, or should I
rethink this and save myself from a potentially nasty design flaw? Is
there a design pattern I could use here?


I've given you code below:

class Other;

class Base {
Other& other_; // this is private
protected:
virtual ~Base() = 0;
Base(Other& o) : other_(o) {}


You are correct - you need an accessor here. E.g.:

void doAction() { other.doAction( ); }

or

const Other& other() const { return other_; }

or whatever... It's not clear (to me, anyway) what you are trying to
do.
};

Base::~Base() {}

class Derived : public Base {
public:
Derived(Other& o) : Base(o) {}
};

Thanks for your help, Tom. I hope my questions don't seem too stupid.


You're welcome, and they're not stupid. You might consider picking up
a copy of Effective C++ (3d ed.), which includes a lot of good advice.

Best regards,

Tom

Dec 10 '05 #6

Thomas Tutone wrote:
an************* *@googlemail.co m wrote:
Thomas Tutone wrote:
an************* *@googlemail.co m wrote:
> I have an ABC with a protected member that is a reference to an object
> of an ABC type:
>
> class ABC
> {
> public:
> virtual ~ABC() = 0;

your destructor should be protected, not public.


Why is that? I can understand the constructor being protected, but not
the destructor. Won't this mean that delete won't be able to call the
destructors of inherited classes through the ABC interface?


Perhaps you are missing the point. ABC's destructor will never be
called directly - because the destructor is virtual, it will be the
destructor of the derived class that will be called, which will in turn
call the base destructor. The derived destructor has access to the
protected functions of its parent.


Okay, but I want to use ABC as an interface. For example:

ABC* inst = new SomeDerivedClas s();
delete inst; // I can't delete it, ABC's destructor is protected

I'm sure this isn't an unusual thing to do, which is why I don't
understand having a protected destructor in ABC.

Dec 10 '05 #7
On 10 Dec 2005 13:29:14 -0800, "Thomas Tutone"
<Th***********@ yahoo.com> wrote:
Perhaps you are missing the point. ABC's destructor will never be
called directly - because the destructor is virtual, it will be the
destructor of the derived class that will be called, which will in turn
call the base destructor. The derived destructor has access to the
protected functions of its parent.


This is not true. If the base class' destructor is protected, clients
using the classes will not be able to call delete on a pointer to the
base class. They will, however, be able to call delete on pointers to
the derived classes.

There are situations where this is the desired behavior, e.g. when a
virtual destructor is not desirable or needed, as with private
inheritance.

--
Bob Hairgrove
No**********@Ho me.com
Dec 10 '05 #8

an************* *@googlemail.co m wrote:
Thomas Tutone wrote:
an************* *@googlemail.co m wrote:
Thomas Tutone wrote:
> an************* *@googlemail.co m wrote:
> > I have an ABC with a protected member that is a reference to an object
> > of an ABC type:
> >
> > class ABC
> > {
> > public:
> > virtual ~ABC() = 0;
>
> your destructor should be protected, not public.

Why is that? I can understand the constructor being protected, but not
the destructor. Won't this mean that delete won't be able to call the
destructors of inherited classes through the ABC interface?
Perhaps you are missing the point. ABC's destructor will never be
called directly - because the destructor is virtual, it will be the
destructor of the derived class that will be called, which will in turn
call the base destructor. The derived destructor has access to the
protected functions of its parent.


Okay, but I want to use ABC as an interface. For example:

ABC* inst = new SomeDerivedClas s();
delete inst; // I can't delete it, ABC's destructor is protected


Not true. When you call "delete inst," what does the compiler insert
code to do? Well, first, it calls the destructor for inst. Now inst is
declared as a pointer to ABC. ABC has a virtual destructor. So
instead of calling the destructor for an ABC, the compiler inserts code
to call the destructor for SomeDerivedClas s, which presumably has a
_public_ destructor. SomeDerivedClas s, in turn, calls ABC's
destructor, which SomeDerivedClas s is entitled to do, because its
parent is ABC, and a derived class can call a protected function in its
parent. So your example will work fine, nothwithstandin g your comment.
I'm sure this isn't an unusual thing to do, which is why I don't
understand having a protected destructor in ABC.


I hope this makes sense now. If it doesn't, you need to re-review the
concept of virtual functions.

Best regards,

Tom

Dec 10 '05 #9

Thomas Tutone wrote:
an************* *@googlemail.co m wrote:
Thomas Tutone wrote:
an************* *@googlemail.co m wrote:
> Thomas Tutone wrote:
> > an************* *@googlemail.co m wrote:
> > > I have an ABC with a protected member that is a reference to an object
> > > of an ABC type:
> > >
> > > class ABC
> > > {
> > > public:
> > > virtual ~ABC() = 0;
> >
> > your destructor should be protected, not public.
>
> Why is that? I can understand the constructor being protected, but not
> the destructor. Won't this mean that delete won't be able to call the
> destructors of inherited classes through the ABC interface?

Perhaps you are missing the point. ABC's destructor will never be
called directly - because the destructor is virtual, it will be the
destructor of the derived class that will be called, which will in turn
call the base destructor. The derived destructor has access to the
protected functions of its parent.


Okay, but I want to use ABC as an interface. For example:

ABC* inst = new SomeDerivedClas s();
delete inst; // I can't delete it, ABC's destructor is protected


Not true. When you call "delete inst," what does the compiler insert
code to do? Well, first, it calls the destructor for inst. Now inst is
declared as a pointer to ABC. ABC has a virtual destructor. So
instead of calling the destructor for an ABC, the compiler inserts code
to call the destructor for SomeDerivedClas s, which presumably has a
_public_ destructor. SomeDerivedClas s, in turn, calls ABC's
destructor, which SomeDerivedClas s is entitled to do, because its
parent is ABC, and a derived class can call a protected function in its
parent. So your example will work fine, nothwithstandin g your comment.


You know what - I'm having a bad day. You are absolutely right and I
am wrong. My apologies for confusing the issue. The destructor should
indeed be public. Glad you're awake, even if I'm not.

Best regards,

Tom

Dec 10 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
1765
by: Patrick | last post by:
I want to achieve the following behaviour but I am having trouble getting there...bare with me im knew to c++ , so its probably rather trivial! To have a class ClassA, and composed within this class is an instance of another class, ClassB. I want to have a method getClassB that returns a reference to the instance of ClassB composed within ClassA. So when a client calls getClassB they are supplied with a reference to the instance of...
4
2672
by: fog | last post by:
Given: class A; and B "has-a" A. The composition relationship between A and B can be implemented in three ways: =================== # 1. class B {
7
1978
by: preetam | last post by:
Hi, This question is more towards design than towards c++ details. By looking at books on design patterns and various google threads on the same topic, I see that composition is favoured to inheritence. One more article I read was Allen holub's "Why extends is evil". http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html One general advice I found was that - extending behaviour is better done with interfaces and...
9
2311
by: Code4u | last post by:
My colleagues and I have been discussing techniques for implementing interfaces in C++. We're looking for a mechanism similar to COM's QueryInterface, in which a certain types of objects can be queried, at run-time, for a particular interface and if it is supported, a pointer or reference to that interface passed to the caller. Two possible implementations came up, multiple inheritance and composition. Using MI the class multiply inherits...
11
2804
by: Milind | last post by:
Hi, I was trying to implement a composition relation, somthing of the following type: class A { public: class B {
4
10961
by: cmrchs | last post by:
Hi, how do I implement aggregation and how composition in C# ? When I say : an Airplane has a Pilot then I use aggregation but when I say : an Airplane has a Cockpit then I use composition. How do I implement the difference in C# ? Here's what I try : class Pilot
4
14443
by: Frederik Vanderhaegen | last post by:
Hi, Can anyone explain me the difference between aggregation and composition? I know that they both are "whole-part" relationships and that composition parts are destroyed when the composition whole is destroyed. Under a "whole-part" relationship I understand the following: the whole can't exists without the parts, but can the parts exist without the hole? f.e.: a car can't exist without an engine private engine _Engine
2
14816
by: Gary Wessle | last post by:
Hi what is the difference "in code writing" between aggregation and composition? is the following correct? aggregation (life time of both objects are independent). class A{ /* ... */ }; class B{ A& a; /* ... */};
4
5501
by: fireball | last post by:
hi, I got confused for a moment about creating data structure for UML composition (strong aggregation) relation one-to-many. I used Rose/DataModeler to do so. <filled_diamond>-------- I got P/FK (primary key of my component is foreign key of it's container) in my child table: Parent: PK Parent_ID
7
3062
by: snewman18 | last post by:
In learning about design patterns, I've seen discussion about using inheritance when an object's relationship to another object is 'is-a' and composition when the relationship is 'has-a'. Since this is all new and I'm still learning, I was hoping someone can give me some pointers on best practices on applying these ideas. If my logic is incorrect on anything, please don't hesitate to tell me where I'm wrong - I'm completely open to any...
0
8344
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8857
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8764
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8633
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
6186
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4180
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4347
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2762
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
1993
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.