Consider the following short but multifile example:
// ************************** unit.h **************************
#pragma once
#include <memory>
struct S;
struct B {
B(int) {};
virtual ~B() {};
};
struct D : B {
D(int);
~D() override;
std::unique_ptr<S> p;
};
// ************************** unit.cpp **************************
#include "unit.h"
struct S {};
D::D(int i) : B(i) {}
D::~D() = default;
// ************************** prog.cc **************************
#include "unit.h"
int main()
{
D d(42);
}
There are two classes with inheritance: base B and derived D. D class contains a unique_ptr member definition with only declared class S. To make this scheme work I need to define both constructor and destructor of class D out-of-line (i.e. implemented in unit.cpp, where the full definition of S is visible).
The question: is it possible to use the using B::B; declaration in the D class inherit the B's constructors to prevent writing manually D::D(int i) : B(i) {}, but make this inheritance out-of-line in order to prevent compilation error?
error: invalid application of 'sizeof' to an incomplete type 'S'
is it possible to use the using B::B; declaration in the D class inherit the B's constructors to prevent writing manually D::D(int i) : B(i) {}
It is possible.
Along with the forward declaration of struct S also declare its deleter:
struct S;
struct SDeleter { void operator()(S*) const; }; // Defined elsewhere.
And then:
struct D : B {
using B::B;
std::unique_ptr<S, SDeleter> p;
};
The definition of void SDeleter::operator()(S*) const must be provided in another translation unit (.cc) that has access to the definition of S.
Related
I have 3 classes:
Class A
Class B
Class C
In class A, 2 methods are declared, one is void, the second is virtual void.
The virtual void Method2 is defined in class B.
In class C, I call Method1 and Method2;
As a result, I get the following error:
error: 'void Base::A::Method1()' is inaccessible within this context
error: 'Base::A' is not an accessible base of ‘Main::B’
namespace Base {
class A {
public:
A() {}
void Method1() {std::cout << "it is method1\n";}
virtual void Method2() =0;
}; // class A
} // namespace Base
namespace Main {
class B : A {
public:
B() {}
void Method2() {}
}; // class B
class C {
public:
C() {}
void Handle() {
b->Method1(); // it is good
b->Method2(); // this is error
}
private:
std::unique_ptr<B> b;
}; // class C
} // namespace Main
What could be the problem?
You made two errors in one instruction, the declaration of class B. In the context of
namespace Base {
class A {...}
}
this declaration
namespace Main {
class B : A {
declares B as a class inheriting from A or some class in the current hierarchy of namespaces. The compiler will try Main::A and won't find it. It will then try the global namespace, ::A, and will also fail to find A there. It will certainly won't try namespaces that are outside the current namespace hierarchy, in particular, it certainly won't try Base::A. Having failed to find a class matching A, it will stop with an error.
The second error is in that you inherit the base class privately. This means that the information about this inheritance is invisible outside class B, so that you cannot call any of the base class members outside B.
Solution:
namespace Main {
class B : public Base::A {
Why does this code:
class A
{
public:
explicit A(int x) {}
};
class B: public A
{
};
int main(void)
{
B *b = new B(5);
delete b;
}
Result in these errors:
main.cpp: In function ‘int main()’:
main.cpp:13: error: no matching function for call to ‘B::B(int)’
main.cpp:8: note: candidates are: B::B()
main.cpp:8: note: B::B(const B&)
Shouldn't B inherit A's constructor?
(this is using gcc)
If your compiler supports C++11 standard, there is a constructor inheritance using using (pun intended). For more see Wikipedia C++11 article. You write:
class A
{
public:
explicit A(int x) {}
};
class B: public A
{
using A::A;
};
This is all or nothing - you cannot inherit only some constructors, if you write this, you inherit all of them. To inherit only selected ones you need to write the individual constructors manually and call the base constructor as needed from them.
Historically constructors could not be inherited in the C++03 standard. You needed to inherit them manually one by one by calling base implementation on your own.
For templated base classes, refer to this example:
using std::vector;
template<class T>
class my_vector : public vector<T> {
public:
using vector<T>::vector; ///Takes all vector's constructors
/* */
};
Constructors are not inherited. They are called implicitly or explicitly by the child constructor.
The compiler creates a default constructor (one with no arguments) and a default copy constructor (one with an argument which is a reference to the same type). But if you want a constructor that will accept an int, you have to define it explicitly.
class A
{
public:
explicit A(int x) {}
};
class B: public A
{
public:
explicit B(int x) : A(x) { }
};
UPDATE: In C++11, constructors can be inherited. See Suma's answer for details.
This is straight from Bjarne Stroustrup's page:
If you so choose, you can still shoot yourself in the foot by inheriting constructors in a derived class in which you define new member variables needing initialization:
struct B1 {
B1(int) { }
};
struct D1 : B1 {
using B1::B1; // implicitly declares D1(int)
int x;
};
void test()
{
D1 d(6); // Oops: d.x is not initialized
D1 e; // error: D1 has no default constructor
}
note that using another great C++11 feature (member initialization):
int x = 77;
instead of
int x;
would solve the issue
You have to explicitly define the constructor in B and explicitly call the constructor for the parent.
B(int x) : A(x) { }
or
B() : A(5) { }
How about using a template function to bind all constructors?
template <class... T> Derived(T... t) : Base(t...) {}
Correct Code is
class A
{
public:
explicit A(int x) {}
};
class B: public A
{
public:
B(int a):A(a){
}
};
main()
{
B *b = new B(5);
delete b;
}
Error is b/c Class B has not parameter constructor and second it should have base class initializer to call the constructor of Base Class parameter constructor
Here is how I make the derived classes "inherit" all the parent's constructors. I find this is the most straightforward way, since it simply passes all the arguments to the constructor of the parent class.
class Derived : public Parent {
public:
template <typename... Args>
Derived(Args&&... args) : Parent(std::forward<Args>(args)...)
{
}
};
Or if you would like to have a nice macro:
#define PARENT_CONSTRUCTOR(DERIVED, PARENT) \
template<typename... Args> \
DERIVED(Args&&... args) : PARENT(std::forward<Args>(args)...)
class Derived : public Parent
{
public:
PARENT_CONSTRUCTOR(Derived, Parent)
{
}
};
derived class inherits all the members(fields and methods) of the base class, but derived class cannot inherit the constructor of the base class because the constructors are not the members of the class. Instead of inheriting the constructors by the derived class, it only allowed to invoke the constructor of the base class
class A
{
public:
explicit A(int x) {}
};
class B: public A
{
B(int x):A(x);
};
int main(void)
{
B *b = new B(5);
delete b;
}
Google c++ style has the following. I don't understand why forward declaration will call f(void*).
It can be difficult to determine whether a forward declaration or a full #include is needed. Replacing an #include with a forward declaration can silently change the meaning of code:
// b.h:
struct B {};
struct D : B {};
// good_user.cc:
#include "b.h"
void f(B*);
void f(void*);
void test(D* x) { f(x); } // calls f(B*)
If the #include was replaced with forward decls for B and D, test() would call f(void*).
Consider the two cases individually. By replacing the #include with the header's content, we first have :
struct B {};
struct D : B {};
void f(B*) {}
void f(void*) {}
void test(D* x) { f(x); }
There are two possible overloads. Since D inherits from B then D* is implicitly convertible to B*. Out of B* and void* the first is a better match so that overload is chosen. But in the case of a forward declared B and D :
struct B;
struct D;
void f(B*) {}
void f(void*) {}
void test(D* x) { f(x); }
D is not known to inherit from B so there is no implicit conversion possible from D* to B*. The only matching overload is f(void*).
I have 5 classes (A,B,C,D,E), each of which will have their own class and header files.
class A{};
class B
{
B(A&a);
};
class C
{
C(B&b);
};
class D:public A
{};
class E:public D
{
vector<C*> vc;
};
Forward declaration will not work because I also have a lot of sharepointers being used in each of those classes.
You can use forward declarations for shared pointers as well, you just need to forward declare a destructor function object as well.
Header:
struct A;
shared_ptr<A> create_A();
Impl:
struct A { ... };
struct A_destroyer { void operator()(A *p) { delete p; } };
shared_ptr<A> create_A() { return shared_ptr<A>(new A(), A_destroyer()); }
Each class can declare a destructor and define that destructor in a source including the header for the appropriate type destructed by unique/shared pointer. Than a simple forward of that type in the header will do it.
#include <memory>
// header B
struct A;
struct B {
~B();
std::shared_ptr<A> a;
};
// header A
struct A {};
// source B
#include "a"
#include "b"
B::~B() {}
I have found a similar question here, but my intent is little different.
class B is the embedding class while class A is the embedded class. I want to let B::A have access to member functions of class B. I have seen compilation errors through g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2. The detailed errors are as follows:
~/Documents/C++ $ g++ embed.cpp
embed.cpp:5:7: error: ‘B’ has not been declared
embed.cpp: In constructor ‘B::B()’:
embed.cpp:10:27: error: invalid use of incomplete type ‘struct B::A’
embed.cpp:14:9: error: forward declaration of ‘struct B::A’
Is there a way that I can make it work?
Thank you
#include <iostream>
#include <string>
using namespace std;
class B
{
public:
B() : impl(new B::A(this)) {}
~B(){}
private:
class A; // want to hide the implementation of A
A* impl;
};
class B::A
{
public:
A(B* _parent) : parent(_parent) {} // let embedded class A has access to this parent class
~A() { parent = NULL; }
B* parent;
};
int main(void)
{
return 0;
}
This problem is solved easily if you follow the convention of having the header in one file and the implementation in another.
In file b.h:
class B
{
public:
B();
~B();
private:
class A; // want to hide the implementation of A
A* impl;
};
class B::A
{
public:
A(B* _parent);
~A();
B* parent;
};
In file b.cpp:
B::B(void)
:impl(new A(this))
{
}
//other methods and such
My compiler was giving me a different error: in the constructor for B, you were default-constructing an object that had no default constructor (because it's an incomplete class). The solution is to implement the B constructor after class A has been fully defined, and the header/implementation separation is a natural way to achieve that.
Just separate the definition from the declaration:
class B
{
public:
B();
~B();
private:
class A; // want to hide the implementation of A
A* impl;
};
// define class B::A
B::B() : impl(new B::A(this)) { }
B::~B() { }
By the time you need to call B::A::A(), it'll already be defined.
You could separate this into three files, B.hpp, BA.hpp and B.cpp, and you would only need to ship B.hpp to the client.
You just can't. If you want to use A, then you have to know all about A. But there maybe another approach:
#include <iostream>
#include <string>
using namespace std;
class B
{
public:
B() : impl(newA()) {}
~B(){}
private:
static Abase *newA();
class Abase{}; // want to hide the implementation of A
Abase* impl;
friend class A;
};
And you define you class A : B::Abase in another file, and implement B::newA() to return a pointer to A.
Code not tested.