473,796 Members | 2,798 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Restricting base class visibility

I have a system that looks like this:

class AbstractBase { /* ... */ };
template <class T> class Impl : public AbstractBase { /* ... */ };
// ...
Impl<int> i;
Impl<float> f;
std::vector<Abs tractBase*> vec;
vec.push_back(& i);
vec.push_back(& f);
// ...

It works. However, at the moment, class AbstractBase has public
visibility - anyone can subclass it. Ideally, the only subclasses of
AbstractBase should be instantiations of Impl. Impl, on the other hand,
can (and should) be instantiable by anyone. Is it possible for me to
somehow hide AbstractBase to restrict what classes can subclass it?

Thanks,
Rennie deGraaf
Jan 5 '06 #1
12 1789
Rennie deGraaf wrote:
I have a system that looks like this:

class AbstractBase { /* ... */ };
template <class T> class Impl : public AbstractBase { /* ... */ };
// ...
Impl<int> i;
Impl<float> f;
std::vector<Abs tractBase*> vec;
vec.push_back(& i);
vec.push_back(& f);
// ...

It works. However, at the moment, class AbstractBase has public
visibility - anyone can subclass it. Ideally, the only subclasses of
AbstractBase should be instantiations of Impl. Impl, on the other hand,
can (and should) be instantiable by anyone. Is it possible for me to
somehow hide AbstractBase to restrict what classes can subclass it?

You can make the constructor of AbstractBase private, then make Impl a
friend of AbstractBase. That way, only Impl knows how to construct the
AbstractBase sub-object.

But I'm curious, why restrict the use of AbstractBase in this way?

Hope this helps,
-shez-

Jan 5 '06 #2

Rennie deGraaf wrote:
I have a system that looks like this:

class AbstractBase { /* ... */ };
template <class T> class Impl : public AbstractBase { /* ... */ };
// ...
Impl<int> i;
Impl<float> f;
std::vector<Abs tractBase*> vec;
vec.push_back(& i);
vec.push_back(& f);
// ...

It works. However, at the moment, class AbstractBase has public
visibility - anyone can subclass it. Ideally, the only subclasses of
AbstractBase should be instantiations of Impl. Impl, on the other hand,
can (and should) be instantiable by anyone. Is it possible for me to
somehow hide AbstractBase to restrict what classes can subclass it?


The obvious question to ask is why are AbstractBase and Impl distinct
classes to start with, if AbstractBase is meant to have only a single
subclass.

Greg

Jan 5 '06 #3
Greg wrote:
The obvious question to ask is why are AbstractBase and Impl distinct
classes to start with, if AbstractBase is meant to have only a single
subclass.
From the OP's code, it looks like he wants to create a vector

containing heterogenous objects. The problem with his approach is that
the <AbstractBase *> parameter for vector does not preserve value
semantics. A better approach would be to use something boost::any or
boost::variant, where value-semantics are maintained.

-shez-

Jan 5 '06 #4
Greg wrote:
Rennie deGraaf wrote:
I have a system that looks like this:

class AbstractBase { /* ... */ };
template <class T> class Impl : public AbstractBase { /* ... */ };
// ...
Impl<int> i;
Impl<float> f;
std::vector<Abs tractBase*> vec;
vec.push_back(& i);
vec.push_back(& f);
// ...

It works. However, at the moment, class AbstractBase has public
visibility - anyone can subclass it. Ideally, the only subclasses of
AbstractBas e should be instantiations of Impl. Impl, on the other hand,
can (and should) be instantiable by anyone. Is it possible for me to
somehow hide AbstractBase to restrict what classes can subclass it?

The obvious question to ask is why are AbstractBase and Impl distinct
classes to start with, if AbstractBase is meant to have only a single
subclass.

Greg


What I need is an STL container (I'm actually using an std::map, but an
std::vector was simpler for the example) containing a bunch of different
instantiations of Impl. In other words, a container can can store an
Impl<int> and an Impl<string>, but not an int or a string. AFAIK, C++
doesn't define references or pointers to templates, only to template
instantiations, so I need to refer to objects of Impl<int> and
Impl<string> through a base class.

Since the STL doesn't seem to play nicely with polymorphic types, I have
to store pointers to my objects, rather than the objects themselves, and
handle allocation myself. It's a pain, but I don't know any better
ways. I'm open to suggestions, if you have them.

Rennie
Jan 5 '06 #5
Rennie deGraaf wrote:

What I need is an STL container (I'm actually using an std::map, but an
std::vector was simpler for the example) containing a bunch of different
instantiations of Impl. In other words, a container can can store an
Impl<int> and an Impl<string>, but not an int or a string. AFAIK, C++
doesn't define references or pointers to templates, only to template
instantiations, so I need to refer to objects of Impl<int> and
Impl<string> through a base class.

Since the STL doesn't seem to play nicely with polymorphic types, I have
to store pointers to my objects, rather than the objects themselves, and
handle allocation myself. It's a pain, but I don't know any better
ways. I'm open to suggestions, if you have them.


As shezan suggested, you can solve this by having private Constructor
in AbstractBase

#include <vector>

class AbstractBase {
protected:
virtual ~AbstractBase() { }
private:
AbstractBase(){ }
template<class T> friend class Impl;

};

template <class T> class Impl : public AbstractBase {
T i;
};
class Zoo : public AbstractBase {
};
// Zoo cannot be instantiated because constructor of base class is
private.

int main()
{
Impl<int> i;
Impl<float> f;
// Zoo z; // not allowed

std::vector<Abs tractBase*> v;
v.push_back(&i) ;
v.push_back(&f) ;

// v.push_back(&z) ; // Error.

}

Jan 5 '06 #6
Rennie deGraaf wrote:
Since the STL doesn't seem to play nicely with polymorphic types, I have
to store pointers to my objects, rather than the objects themselves, and
handle allocation myself. It's a pain, but I don't know any better
ways. I'm open to suggestions, if you have them.

I guess I should rephrase my original question so: What virtual
functions are you going to have in 'AbstractBase'? If there are no
virtual functions, there should be no need for inheritance. If there
*are* virtual functions, when why make 'AbstractBase' completely
hidden?

I suggested 'boost::any' earlier, but if you want to restrict your
container to only contain 'Impl' objects, then it is reasonably
straightforward to adapt 'boost::any' to restrict only 'Impl' types.
Something like:
class AnyImpl {
// PRIVATE DATA MEMBERS
boost::any d_any;

public:
template <typename TYPE>
AnyImpl(const Impl<TYPE>& value) : d_any(value) { }

template <typename TYPE>
AnyImpl& operator=(const Impl<TYPE>& value) { d_any = value; }
};
Now you can create vector<AnyImpl> or map<AnyImpl, AnyImpl>.
Hope this helps,
-shez-

Jan 5 '06 #7
Shezan Baig wrote:
Rennie deGraaf wrote:
I have a system that looks like this:

class AbstractBase { /* ... */ };
template <class T> class Impl : public AbstractBase { /* ... */ };
// ...
Impl<int> i;
Impl<float> f;
std::vector<Abs tractBase*> vec;
vec.push_back(& i);
vec.push_back(& f);
// ...

It works. However, at the moment, class AbstractBase has public
visibility - anyone can subclass it. Ideally, the only subclasses of
AbstractBas e should be instantiations of Impl. Impl, on the other hand,
can (and should) be instantiable by anyone. Is it possible for me to
somehow hide AbstractBase to restrict what classes can subclass it?

You can make the constructor of AbstractBase private, then make Impl a
friend of AbstractBase. That way, only Impl knows how to construct the
AbstractBase sub-object.


Of course, doing this would make *all* of AbstractBase's private methods
and data accessible to Impl. Is it possible to only make Impl's
constructor a friend to AbstractBase? I can't find anything on the
subject, and can't figure out any syntax that compiles.
But I'm curious, why restrict the use of AbstractBase in this way?


My code assumes that all objects that it pulls out of vec are
instantiations of Impl. If someome subclasses AbstractBase with
something else and gets it into vec, then my code with throw an
exception with an error message that assumes a completely different
problem. My code can't tell the difference between a specialization of
Impl that it doesn't know about and something that isn't an Impl at all.

Also, I intend people using my system to write specializations of Impl,
and don't want to make it possible for people to get confused and try to
subclass AbstractBase instead. If I make Impl a friend of AbstractBase
and make AbstractBase's constructor private, then this can't happen, but
then people might mess around with AbstractBase's private data and
totally s*crew up the system. Neither is a critical problem (unless
someome finds a way to make a buffer overflow or something out of it),
but I'd rather have neither, and I'm not sure which is worse.

Rennie
Jan 5 '06 #8
> Rennie deGraaf" <ca.ucalgary.cp sc@degraaf> wrote:
Rennie deGraaf wrote:
I have a system that looks like this:

class AbstractBase { /* ... */ };
template <class T> class Impl : public AbstractBase { /* ... */ };
// ...
Impl<int> i;
Impl<float> f;
std::vector<Abs tractBase*> vec;
vec.push_back(& i);
vec.push_back(& f);
// ...

It works. However, at the moment, class AbstractBase has public
visibility - anyone can subclass it. Ideally, the only subclasses of
AbstractBase should be instantiations of Impl. Impl, on the other hand,
can (and should) be instantiable by anyone. Is it possible for me to
somehow hide AbstractBase to restrict what classes can subclass it?


What I need is an STL container (I'm actually using an std::map, but an
std::vector was simpler for the example) containing a bunch of different
instantiations of Impl. In other words, a container can can store an
Impl<int> and an Impl<string>, but not an int or a string. AFAIK, C++
doesn't define references or pointers to templates, only to template
instantiations, so I need to refer to objects of Impl<int> and
Impl<string> through a base class.

Since the STL doesn't seem to play nicely with polymorphic types, I have
to store pointers to my objects, rather than the objects themselves, and
handle allocation myself. It's a pain, but I don't know any better
ways. I'm open to suggestions, if you have them.


I would suggest looking into a discriminated union or similar, variant type
(such as Boost's variant) as an alternative solution. I think either of
those approaches would involve less "housekeepi ng" chores, require fewer
lines code, and overall be simply easier to manage than the implementation
described above. The benefit of a union or variant class derives from having
just one class do the work currently slated for one base class and several,
derived classes - in short - an entire class hierarchy.

Greg

Jan 5 '06 #9

"Neelesh Bodas" <ne***********@ gmail.com> skrev i meddelandet
news:11******** ************@g1 4g2000cwa.googl egroups.com...
Rennie deGraaf wrote:

What I need is an STL container (I'm actually using an std::map,
but an
std::vector was simpler for the example) containing a bunch of
different
instantiations of Impl. In other words, a container can can store
an
Impl<int> and an Impl<string>, but not an int or a string. AFAIK,
C++
doesn't define references or pointers to templates, only to
template
instantiations, so I need to refer to objects of Impl<int> and
Impl<string> through a base class.

Since the STL doesn't seem to play nicely with polymorphic types, I
have
to store pointers to my objects, rather than the objects
themselves, and
handle allocation myself. It's a pain, but I don't know any better
ways. I'm open to suggestions, if you have them.
As shezan suggested, you can solve this by having private
Constructor
in AbstractBase

#include <vector>

class AbstractBase {
protected:
virtual ~AbstractBase() { }
private:
AbstractBase(){ }
template<class T> friend class Impl;

};

template <class T> class Impl : public AbstractBase {
T i;
};
class Zoo : public AbstractBase {
};
// Zoo cannot be instantiated because constructor of base class is
private.


But it doesn't stop the pervasive intruder!

struct ooZ {};

template<>
class Impl<ooZ> : public AbstractBase {
// whatever Zoo wants to do!
};

typedef Impl<ooZ> Zoo;


int main()
{
Impl<int> i;
Impl<float> f;
// Zoo z; // not allowed
Now it is allowed!

std::vector<Abs tractBase*> v;
v.push_back(&i) ;
v.push_back(&f) ;

// v.push_back(&z) ; // Error.

}

Jan 10 '06 #10

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

Similar topics

5
1686
by: Dan =o\) | last post by:
given this brief scenario, is this possible somehow? class A { public SomeMethod() { } }
1
2424
by: mdb | last post by:
I'm trying to restrict the characters that are valid in a textBox, so I derived from System.Windows.Forms.TextBox, and overrode WndProc, catching the key up/down messages... Everything works except the arrow keys - the text cursor never moves. Why won't the arrows work? I know I'm catching the correct WParam values... protected override void WndProc(ref Message m) { if ((m.Msg == 256) || (m.Msg == 258)) {
2
1373
by: clintonG | last post by:
I've created a base class that inherits from System.Web.UI.Page. I've been using Page_PreInit in the base class to change Themes. I'm using MasterPages and need a bunch of code in each content page to manage the UI. For the most part this UI code is the same across many pages although their will be some conditional circunstances. So I thought "put the logic in the base class so I don't even have to call any methods in each content page."...
1
2177
by: Piper707 | last post by:
Hi, I'd like to know if there are any more ways of restricting an XML document to having only non-empty tags (containing Strings). I can think of 2 ways: 1) <xs:simpleType name="tagName">
5
3403
by: EqDev | last post by:
I have a class that is a control derived from UserControl. I want to use serialization and deserialization with this calss but I get an exception "Cannot serialize member System.ComponentModel.Component.Site of type System.ComponentModel.ISite because it is an interface.". I am not interested in serializing any member from the base class only the properties in the derived class. How can I prevent the entire base class from being...
4
1436
by: Colin Desmond | last post by:
Is it possible to write an attribute that changes the visibility of a class (public/private) etc based on some pre-compiler define symbol? We're writing some classes which will be called by an external (bespoke) test harness, so we want then to be public in the assembly when we're testing, and private in the class the rest of the time. For example
11
2879
by: Darren.Ratcliffe | last post by:
Hi guys Posted what was probably a rather confusing post about this the other day, so I am going to have another go and see if I can make more sense. This sis purely a I've got a base class called animal, and from within animal you can access lots more classes such as feline, canine, reptile and amphibian.....
2
1881
by: WittyGuy | last post by:
Hi My class looks something like this: class Base { public: Base () {} ~Base () {} // No virtual dtor in the base class private: };
10
3143
by: Janis Papanagnou | last post by:
The task seems simple but I am not sure whether this is possible or even the right way to look at it... I have <td class="X"elements where "X" is a placeholder for class names "A", "B", etc. Now I want to display/hide all <tdelements of a certain class, say "A". The static CSS equivalent would be <style type="text/css"> .A { visibility:visible; } .B { visibility:hidden; }
0
9685
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9535
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
10244
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
6802
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5454
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
5582
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4130
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
3744
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2931
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.