Can not call constructors of inherited objects



  • Hello!

    I have the following

    class A
    {
    public:
      struct {
        B b; //B and C -- some classes which can be bitwise copied,
        C c; //  thus I do not need in copy constructor of this structure
      } dataContainer;
    
      D d; 
    
      A(void):dataContainer.b(1.0),dataContainer.c('a'),d(-3){;} //Call constructors of inherited objects -- error here :(
    }
    

    I put some members to the dataContainer structure, because I can need, for example, to make a temporary copy of members from dataContainer , or pass these members to some function etc.

    But compiler do not like the dataContainer.b(1.0) . I hope that this code will skip the dataContainer default constructor (because I do not call it in A constructor) and instead will directly construct dataContainer.b and dataContainer.c with initial values I need.

    Another question: what to do with anonymous struct:

    {
    public:
      struct {
        B b; //B and C -- some classes which can be bitwise copied,
        C c; //  thus I do not need in copy constructor of this structure
      }; //Anonymous struct, all OK here
    
      D d; 
    
      A(void):b(1.0),c('a'),d(-3){;} //Is this OK?
    }
    

    How to make constructor of anonymous struct?


  • Mod

    SAn schrieb:

    Hello!

    I have the following

    class A
    {
    public:
      struct {
        B b; //B and C -- some classes which can be bitwise copied,
        C c; //  thus I do not need in copy constructor of this structure
      } dataContainer;
    
      D d; 
    
      A(void):dataContainer.b(1.0),dataContainer.c('a'),d(-3){;} //Call constructors of inherited objects -- error here :(
    }
    

    I put some members to the dataContainer structure, because I can need, for example, to make a temporary copy of members from dataContainer , or pass these members to some function etc.

    Being an unnamed structure, it cannot be used to declare a function parameter or return type - this also means that you cannot create a function to serve as a pseudo-constructor (except perhaps a template function through type deduction, but we'll ignore that here). Giving the struct a name should solve the problem, you could then declare a proper constructor for it or use a function instead (that it may stay a POD if necessary).

    class A
    {
    public:
      struct dataContainerType {
        dataContainerType(const B& b,const C& c) : b(b), c(c) {} // use constructor or
        static dataContainerType make(const B& b,const C& c) { dataContainerType x = { b,c }; return x; } // ordinary function
        B b;
        C c;
      } dataContainer;
    
      D d; 
    
      A(void):dataContainer(dataContainerType::make(1.0,'a'))
    }
    

    Either soultion is equally efficient, as the copy that would have to be made within the function make may be eliminated at the compiler's discretion (NRVO).
    As for terms, b and c are not inherited members - that would imply that you dervied from them.

    Another question: what to do with anonymous struct:

    {
    public:
      struct {
        B b; //B and C -- some classes which can be bitwise copied,
        C c; //  thus I do not need in copy constructor of this structure
      }; //Anonymous struct, all OK here
    
      D d; 
    
      A(void):b(1.0),c('a'),d(-3){;} //Is this OK?
    }
    

    How to make constructor of anonymous struct?

    There are no anonymous structs (that is, declaring an unnamed struct without declaring an object of that type or a derived type or declaring a typedef name at the same time) in Standard C++. And - as indicated above - an unnamed class cannot have user declared constructors or destructors.



  • Thank you!
    I understand.

    Can I write this way: A(void):dataContainer({1.0,'a'}),d(-3){} ?

    Another problem is that in my code I have the following:

    template<_TTP> _Cell<_CTP>::_Cell(_meshPointer const mesh):
      Structure.parent(NULL),Structure.children(NULL),Structure.fixed(false),Structure.numberOfLeafs(0),
      Structure.newCell(false),Structure.Adress(mesh),Structure.unsplitable(false),Structure.unmergeable(false),[...]
    

    When I reading this code, I see, that the newly constructed cell has no parent, has no children, structure is not fixed and so on...

    When I fix it, it becomes completely unreadable:

    template<_TTP> _Cell<_CTP>::_Cell(_meshPointer const mesh):
      Structure(NULL,NULL,false,0,false,mesh,false,false,[...]), [...]
    


  • If you want it readable in this way, you have to put the assignments in the constructor block, not in its initialization list:

    template<_TTP> _Cell<_CTP>::_Cell(_meshPointer const mesh)
    {
      Structure.parent = NULL;
      Structure.children = NULL;
      Structure.fixed = false;
      //...
    }
    

    Another way are the so called "named constructors":
    http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8



  • The approach of Th69 is ok if Structure's members are of types without nontrivial ctors. Having types with nontrivial ctors in Structure that approach would give a default-construction of that member during initialization and a copy-assignment in Cell's ctor body.
    For structures or classes that have such a long ctor argument list as Structure in your example, one could gain some readability by defining extra types or functions for each (or most) of the ctor arguments.
    The definition of an extra type could look like this:

    struct StrucParent {
      S* par_;   //I don't know what type the parent is, replace that S appropiately
      StrucParent(S* par) : par_(par) {};
    };
    

    and then replace the first argument of Structure's ctor with a StrucParent:

    class Structure {
    /* ... */
      // Structure(S* parent , *....  //replaced
      Structure (StrucParent parent, /*...*/);
    };
    

    And then call the Ctor like this:

    template<_TTP> _Cell<_CTP>::_Cell(_meshPointer const mesh) :
      Structure( StrucParent(NULL),
                 StrucChildren(NULL),
                 StrucFixed(false), /*...*/
               ), [...]
    

    If you cannot (or do not want to) modify Structure's ctor, you could provide some simple inline functions like this:

    inline S* StrucParent(S* par) {return par;}
    inline bool StrucFixed(bool f) {return f;}
    // etc.
    

    And calling the ctor like stated above - but this time the old ctor as you had it before. Here the readability is better than in the original example, without any performance overhead (I'm pretty sure that any compiler will toss away the pass-through functions). The only flaw is that you pollute your surrounding namespace with the names of those functions. That could be solved like that:

    //Structure.hpp
    namespace Struc {
      inline S* Parent(S* par) {return par;}
      inline bool Fixed(bool f) {return f;}
      //etc.
    }
    
    //Cell.hpp
    template<_TTP> _Cell<_CTP>::_Cell(_meshPointer const mesh) :
      Structure( Struc::Parent(NULL),
                 Struc::Children(NULL),
                 Struc::Fixed(false), /*...*/
               ), [...]
    

    Enough readability? 😉

    PS: an advantage of the define-new-types-version is, that you can provide ctors of Structure where you leave out different arguments with the same type - thyt otherwise would be ambigous:

    Structure::Structure(StrucParent, StrucFixed);    //1) ok, presumably children will be set to NULL
    Structure::Structure(StrucChildren, StrucFixed); //2) this time parent = NULL
    
    Structure(S* parent, bool fixed);  //3) same as 1 without new types.
    Structure(S* children, bool fixed); //4) intended to be same as 2) but is abiguous with 3)!!
    


  • Closed thread because it is a spam bot friend 😉


Anmelden zum Antworten