Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

derived class calls wrong base class constructor [duplicate]

Can you explain the output of the following code? And what do I need to do to call the right base class constructor?

Thanks.

#include <vector>
#include <iostream>

template <class CONTAINER> class SequenceComposite {
protected:
    CONTAINER m_data;
public:
    typedef typename CONTAINER::value_type value_type;
    typedef typename CONTAINER::allocator_type allocator_type;
    typedef typename CONTAINER::size_type size_type;
    explicit SequenceComposite(const allocator_type& alloc = allocator_type()) : m_data(alloc) {
        std::cout << std::endl << "SequenceComposite(alloc)" << std::endl;
    }
    explicit SequenceComposite(size_type n, const value_type& val = value_type(),
        const allocator_type& alloc = allocator_type()) : m_data(n, val, alloc) {
        std::cout << std::endl << "SequenceComposite(n, val, alloc)" << std::endl;
    }
    SequenceComposite(const SequenceComposite& x) : m_data(x.m_data) {
        std::cout << std::endl << "SequenceComposite(x)" << std::endl;
    }

};

template <class DTYPE>
class VectorComposite : public virtual SequenceComposite< std::vector<DTYPE> > {
public:
    typedef typename VectorComposite::value_type value_type;
    typedef typename VectorComposite::allocator_type allocator_type;
    typedef typename VectorComposite::size_type size_type;
    explicit VectorComposite(const allocator_type& alloc = allocator_type()) : SequenceComposite< std::vector<DTYPE> >(alloc) {
        std::cout << "VectorComposite(alloc)" << std::endl;
    }
    explicit VectorComposite(size_type n, const value_type& val = value_type(),
        const allocator_type& alloc = allocator_type()) : SequenceComposite< std::vector<DTYPE> >(n, val, alloc) {
        std::cout << "VectorComposite(n, val, alloc)" << std::endl;
    }
    VectorComposite(const VectorComposite& x) : SequenceComposite< std::vector<DTYPE> >(x) {
        std::cout << "VectorComposite(x)" << std::endl;
    }

};

template<typename T> class MyModel : public virtual VectorComposite<T> {
    public:
        MyModel() {
            std::cout << "MyModel()" << std::endl;
        };
        MyModel(const MyModel<T> &vec) : VectorComposite<T>(vec) {
            std::cout << "MyModel(x)" << std::endl;
        }
        MyModel( size_t n, const T& value= 0) : VectorComposite<T>(n, value) {
            std::cout << "MyModel(n, val)" << std::endl;
        }
};

int main() {
    MyModel<float> c(4, 2.0);
    MyModel<float> e(c);

    VectorComposite<float> a(3, 2.0);
    VectorComposite<float> b(c);

    return 0;
}

Output:

SequenceComposite(alloc)
VectorComposite(n, val, alloc)
MyModel(n, val)

SequenceComposite(alloc)
VectorComposite(x)
MyModel(x)

SequenceComposite(n, val, alloc)
VectorComposite(n, val, alloc)

SequenceComposite(x)
VectorComposite(x)

I expected

SequenceComposite(n, val, alloc)
VectorComposite(n, val, alloc)
MyModel(n, val)

SequenceComposite(x)
VectorComposite(x)
MyModel(x)
...
like image 463
Michael Avatar asked Sep 13 '26 07:09

Michael


1 Answers

Virtual base classes are initialized from the constructor of the most derived type. So in the first two examples, the default constructor for SequenceComposite is called. That's the one that takes an allocator_type with a default argument. To use a different constructor, call it from the initializer list of the most derived type.

like image 51
Pete Becker Avatar answered Sep 14 '26 23:09

Pete Becker



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!