Reputation: 21893
So a base class has multiple constructors:
sf::Sprite()
sf::Sprite(const Texture& texture)
sf::Sprite(const Texture& texture, const IntRect& rectangle)
And I'm subclassing this class multiple times:
class Sub : public sf::Sprite {
public:
Sub() : sf::Sprite() {};
Sub(const Texture& texture) : sf::Sprite(texture) {};
Sub(const Texture& texture, const IntRect& rectangle) : sf::Sprite(texture, rectangle) {};
// My subclass specific code
};
As you see, I have to repeat these three constructors for every subclass. Is there a way to avoid this, since the constructors usually don't do anything special? Sometimes I need some class specific initialization though, so it's not always viable to just straight out copy everything.
Upvotes: 21
Views: 3613
Reputation: 45424
If you can just 'inherit' the constructor, i.e. have one with exactly the same arguments, simply use using
as explained in the other answers. However, if your derived
class's constructor has additional arguments and/or requires some class specific initialization, you may use a variadic template.
struct base
{
base(int);
base(std::string const&);
base(some_type const&);
base(std::string const&, some_type const&);
/* ... */
};
struct derived : base
{
template<typename...Args>
derived(some_other_type const&x, Args&&...args)
: base(std::forward<Args>(args)...)
, private_datum(x)
{
construction_details(); // class-specific initialisation
}
private:
some_other_type private_datum;
void construction_details(); // implemented in source code
};
Upvotes: 7
Reputation: 172914
You can accomplish this by inheriting constructors (since C++11).
If the using-declaration refers to a constructor of a direct base of the class being defined (e.g.
using Base::Base;
), all constructors of that base (ignoring member access) are made visible to overload resolution when initializing the derived class.
e.g.
class Sub : public sf::Sprite {
public:
using sf::Sprite::Sprite;
// My subclass specific code
};
If the inherited constructors is used to initialize a Sub
, the sf::Sprite
subobject is initialized using the inherited constructor, and all other members of Sub
are initialized as if by the defaulted default constructor.
If there're some special cases need to be processed, you still can define constructor(s) in Sub
, the inherited constructor with the same signature will be hidden.
As with using-declarations for any other non-static member functions, if an inherited constructor matches the signature of one of the constructors of Derived, it is hidden from lookup by the version found in Derived.
Upvotes: 36
Reputation: 642
You can use the using
keyword to inherit the constructor of your base class, excluding the special ones (default, copy, move). To shorten your default constructor simply use = default
. If you want class specific initialization you can simply write the constructor again, just as you do now.
class Sub : public sf::Sprite {
public:
Sub() = default;
using sf::Sprite::Sprite;
Sub(const Texture& texture)
{
// your custom code.
};
// My subclass specific code
};
Upvotes: 15