inheritance and base constructor

Discussion in 'C++' started by Mike - EMAIL IGNORED, Mar 10, 2006.

  1. 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.
    Mike - EMAIL IGNORED, Mar 10, 2006
    #1
    1. Advertising

  2. Mike - EMAIL IGNORED

    Hippo Guest

    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;

    }
    Hippo, Mar 10, 2006
    #2
    1. Advertising

  3. * 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.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Mar 10, 2006
    #3
  4. Mike - EMAIL IGNORED

    Daniel T. Guest

    In article <>,
    Mike - EMAIL IGNORED <> wrote:

    > 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(); }
    };

    --
    Magic depends on tradition and belief. It does not welcome observation,
    nor does it profit by experiment. On the other hand, science is based
    on experience; it is open to correction by observation and experiment.
    Daniel T., Mar 10, 2006
    #4
  5. Mike - EMAIL IGNORED

    Peter_Julian Guest

    "Mike - EMAIL IGNORED" <> wrote in message
    news:p...
    | 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.
    Peter_Julian, Mar 10, 2006
    #5
  6. Mike - EMAIL IGNORED

    Alex Buell Guest

    On Fri, 10 Mar 2006 03:08:00 -0500 "Peter_Julian"
    <> 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.

    --
    http://www.munted.org.uk

    "Honestly, what can I possibly say to get you into my bed?" - Anon.
    Alex Buell, Mar 10, 2006
    #6
  7. On Fri, 10 Mar 2006 03:47:25 +0100, Alf P. Steinbach wrote:

    > * 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.


    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?
    > A: Because it messes up the order in which people normally read text.
    > Q: Why is it such a bad thing?
    > A: Top-posting.
    > Q: What is the most annoying thing on usenet and in e-mail?
    Mike - EMAIL IGNORED, Mar 11, 2006
    #7
  8. Mike - EMAIL IGNORED

    Peter_Julian Guest

    "Alex Buell" <> wrote in message
    news:...
    | On Fri, 10 Mar 2006 03:08:00 -0500 "Peter_Julian"
    | <> 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.
    Peter_Julian, Mar 11, 2006
    #8
  9. * Mike - EMAIL IGNORED:
    > On Fri, 10 Mar 2006 03:47:25 +0100, Alf P. Steinbach wrote:
    >
    >> * 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.

    >
    > 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.
    Alf P. Steinbach, Mar 11, 2006
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. mrstephengross
    Replies:
    5
    Views:
    586
    Larry I Smith
    May 18, 2005
  2. ali
    Replies:
    4
    Views:
    561
    David Harmon
    Mar 5, 2007
  3. Rahul
    Replies:
    16
    Views:
    1,179
    terminator
    Nov 7, 2007
  4. Generic Usenet Account
    Replies:
    10
    Views:
    2,205
  5. Replies:
    2
    Views:
    695
Loading...

Share This Page