inheritance and base constructor

  • Thread starter Mike - EMAIL IGNORED
  • Start date
M

Mike - EMAIL IGNORED

I have a class that may or may not be inherited.
Its constructor calls a function that should be
called only if the class is not inherited. Is
there a way to tell, other than simply passing
a bool argument?
Thanks for your suggestions.
Mike.
 
H

Hippo

i think u only need add this func in ur base class .
as this simple
class A
{
public:
A()
{
//you only need add the function here.when constructor
a derived class ,it will //transfer here
cout<<"class A constructor"<<endl;
}

};
class B:public A
{
public:
B()
{
cout<<"class B constructor"<<endl;
}

};

int main()
{
B temp;

}
 
A

Alf P. Steinbach

* Mike - EMAIL IGNORED:
I have a class that may or may not be inherited.
Its constructor calls a function that should be
called only if the class is not inherited. Is
there a way to tell, other than simply passing
a bool argument?

You could pass the function as argument, but there's no built-in way in
a class to tell whether it's being inherited. You can limit inheritance
to a set of designated classes (which can be empty), and I think that's
in the FAQ, but that's all. Anyway, this looks like a design problem,
that there's something wrong with the design; details would be welcome.
 
D

Daniel T.

Mike - EMAIL IGNORED said:
I have a class that may or may not be inherited.
Its constructor calls a function that should be
called only if the class is not inherited. Is
there a way to tell, other than simply passing
a bool argument?

Fix your class so it doesn't need to know if a derived class is calling
its constructor. Otherwise, you could do something like this:

class Base
{
public:
Base();
protected:
void call_in_c_tor();
};

class Derived: public Base
{
public:
Derived(): Base() { call_in_c_tor(); }
};
 
P

Peter_Julian

| I have a class that may or may not be inherited.
| Its constructor calls a function that should be
| called only if the class is not inherited. Is
| there a way to tell, other than simply passing
| a bool argument?
| Thanks for your suggestions.
| Mike.

You'll hit a wall since copy ctors will probably cause an issue.

You are describing a relationship that on the one hand depicts a natural
inheritence tree and on the other hand a component tree.

Say you have a class Base and plan to derive from it with a class Derived.
You could consider starting another private inheritence tree and create a
class Component and therefore isolate the 2 trees, after all:

Component is_not_a Derived.

Your code will benefit from such a distinction.
Its also preferable to place that function in the appropriate tree.

class Component is in_terms_of Base, which is in reality a form of
composition...

#include <iostream>
#include <ostream>
#include <vector> // or some other STL container

class Base
{
protected:
Base() { std::cout << "Base()\n"; }
virtual ~Base() = 0 { std::cout << "virtual ~Base()\n"; }
};

class Derived : public Base
{
public:
Derived() : Base() { std::cout << "Derived()\n"; }
~Derived() { std::cout << "virtual ~Derived()\n"; }
};

class Component : private Base /* in_terms_of */
{
void foo() { std::cout << "foo()\n"; }
public:
Component() : Base()
{
std::cout << "Component()\n";
foo();
}
~Component() { std::cout << "virtual ~Component()\n"; }
};

int main()
{
{
std::cout << "--- Derived ---\n";
Derived d;
}
std::cout << "--- Component ---\n";
Component component;

// std::vector< Base > vb;
// vb.push_back(component); // error: conversion innaccessible

std::vector< Component > vc;
vc.push_back(component); // ok, but beware, its a copy !!

return 0;
}

/*
--- Derived ---
Base()
Derived()
virtual ~Derived()
virtual ~Base()
--- Component ---
Base()
Component()
foo()
virtual ~Component()
virtual ~Base()
<------------------- copy c~tor does *not* call foo(),
at least no yet it doesn't
virtual ~Component()
virtual ~Base()
*/

Note that you are free to derive from Component but you can't store
Component objects in a container of Base objects. Which makes sense.
Components are components.

You could derive to expand the Component hierarchy with DerivedComponents
and store these in a container of Components.
DerivedComponents calls foo() as expected except when copy construction is
involved. This may or may not be appropriate but easily corrected.
You'll define Component's copy ctor anyways in the case you plan to store
these.

Component : private Base
{
public:
...
Component(const Component& copy)
{
...
foo(); // maybe, maybe not
}
};

Can you now see why placing foo() in Base is potentially a bad idea?
What you do in Base's copy ctor affects both trees.

And the same arguement applies to the assignment operator.
 
M

Mike - EMAIL IGNORED

* Mike - EMAIL IGNORED:

You could pass the function as argument, but there's no built-in way in
a class to tell whether it's being inherited. You can limit inheritance
to a set of designated classes (which can be empty), and I think that's
in the FAQ, but that's all. Anyway, this looks like a design problem,
that there's something wrong with the design; details would be welcome.

I have changed the design for now. The problem is that in many,
if not all classes that create posix threads, it is necessary to
call pthread_create() after all objects in the inheritance
sequence have been fully created. This would be in the constructor
of the most derived class. If a class may or may not be
inherited, It needs to determine whether pthread_create() should be
called at that level. A less attractive alternative is to require
an initialize() after construction. I would like a way to avoid
this.

Mike
__
A: Then why does most software encourage top-posting?
 
P

Peter_Julian

| On Fri, 10 Mar 2006 03:08:00 -0500 "Peter_Julian"
| <[email protected]> waved a wand and this message magically
| appeared:
|
| > virtual ~Base() = 0 { std::cout << "virtual ~Base()\n"; }
|
| That is incorrect! Remove the '= 0', and all will be well.
|

Technically, the standard requires the pure-virtual Base class to look like
so...
___
class Base
{
public:
Base() { }
virtual ~Base() = 0;
};

Base::~Base() { } // seperate, empty implementation
___
The std::cout output was only for illustrative purposes.

I'll agree that protected access + pure-virtual d~tor is overkill but there
is no doubt that a pure virtual Base class is a requirement here until
proven otherwise. And since its illegal to provide a pure-virtual d~tor
without an implementation...

Surely, a Triangle, Circle or Rectangle are potential 2D object-types but a
Shape is not.
 
A

Alf P. Steinbach

* Mike - EMAIL IGNORED:
I have changed the design for now. The problem is that in many,
if not all classes that create posix threads, it is necessary to
call pthread_create() after all objects in the inheritance
sequence have been fully created. This would be in the constructor
of the most derived class. If a class may or may not be
inherited, It needs to determine whether pthread_create() should be
called at that level. A less attractive alternative is to require
an initialize() after construction. I would like a way to avoid
this.

There are several design choices, then. Off the cuff:

* If possible, let all classes inherit down a chain from some Runnable
class, which can only be used by passing it to the run() function of
a Thread object. Or similar design directly in Thread.

* Full separation of interfaces and concrete classes, where concrete
classes can't be derived from (I don't like this, but).

* Use virtual inheritance to impose a final CRTP derivation to obtain
a concrete class, which you ensure can't be derived from.

You're not the first to have this problem, and last I discussed this
with an acknowledged C++ expert, one who I regard as real expert (in
spite of our disagreement about nearly everything!), he rejected all
three possibilities above as not-quite. However, he was then arguing
for introducing a kind of post-construction-pre-destruction facility to
the language, and I think his arguments were designed to argue the case
for that facility, not to find just a practical design space solution.
Hopefully one of the possibilities above, or some other, will help you.


PS: Please don't quote signatures. A usenet posting signature is
delimited from the preceding text by a line consisting of two hyphens
and a space. Your news client should remove it automatically.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top