This is a basic question but gives me hard time. I have class A and in the header file I want to define another class constructor B from another header file. I tried this code below which I'm sure that's not the correct way.
A.h
class A{
public:
A();
B b(); //Constructor from another Class that defined in another header file
void Operation();
};
I need to call the constructor B in A.h so I can call the constructor B inside constructor A and also use function in Class B inside A::Operation().
A.cpp
#include "A.h"
#include "B.h"
A::A{
b(); //call constructor b
}
void A::Operation(){
b.someFunction(); //use function from class B, error here
}
As expected, the error I got is at b.someFunction()
expression must have class type
Anyone know how to define another class's constructor inside another class header file properly? And call the other constructor inside main class constructor and use the other class's function globally? Sorry for basic and confusing question.
This is not a constructor:
class A{
public:
A();
B b(); //This is a function named b, returning an object of type B
void Operation();
};
Same here:
A::A{
b(); //call function b from above, that returns a B object
}
And same here:
void A::Operation(){
b.someFunction(); // Without invoking method b, you apply the dot operator on the method - which is illegal.
}
You probably want an object of type B, and call someFunction method on it. Maybe you want:
class A{
public:
A();
B b; // this is object named b, of type B
void Operation();
};
And then, if the constructor of B requires parameters, you can:
A::A () : b(constructor parameters) {
}
If there is no need to pass parameters, you can just omit the construction of b, and the language will simply use the default constructor of B (without parameters).
A::A () {
}
The way to invoke or call a constructor of B is to create an instance of B.
The process of creating an instance of B involves calling/invoking a constructor of B. The implementation (aka compiler) takes care of the mechanics of calling the constructor in the process of creating an object. The job of the constructor is to ensure the object is initialised for subsequent use.
Practically speaking, it does not make sense to call a constructor in any context other than object construction. There are some advanced use cases in which a constructor is effectively called manually (e.g. using a placement new expression to initialise a block of memory so it contains an object). However that is done to create an object from the specified memory. This is completely different from what you are seeking.
To construct a B within (code in) a header file a.h, the header file a.h needs to provide visibility of a declaration of B and its constructors.
For example, assuming b.h declares the class B, the header a.h might do
#include "b.h"
class A
{
public:
A() : b() {} ;
void Operation();
private:
B b; // A contains an instance of B
};
In the above (working bottom up) the declaration B b specifies that A has a member of type B, named b.
The definition of As constructor
A() : b() {} ;
uses an initialiser list to initialise (construct) that member b. This assumes the class B has a constructor that can accept no arguments.
The declaration you had within class A (which I have removed from the sample I provided above)
B b(); //Constructor from another Class that defined in another header file
is not what you describe. It is actually a declaration of a member function of class A, which is named b() and returns a B. Calling such a function generally requires B to have a working constructor (typically a copy or move constructor). Such a declaration, however, is not a constructor of B.
just #include "B.h" in A.h and have B b; object in A.h.
#include "B.h"
class A{
A();
B b;
void operation();
}
this way the compiler will have all the information needed from class B constructors and other functions as well for this compilation unit A.cpp and linker will do its job later linking the function name to its logic in other compilation unit B.cpp .
Related
I'm having a problem initializing a shared_ptr member of a class I'm working on.
I have two classes, A and B:
class A {
int _x;
int _y;
public:
A(int, int);
};
A::A(int x, int y) {
_x = x;
_y = y;
}
class B : public A {
std::shared_ptr<A> _a;
public:
B(std::shared_ptr<A>);
};
B::B(std::shared_ptr<A> a) : _a(a) {}
int main() {
std::shared_ptr<A> a = std::make_shared<A>(1, 2);
B b(a);
return 0;
}
I just want class B to hold a std::shared_ptr to an instance of class A.
However, I'm getting the error no matching function for call to A::A() in B's constructor.
I'm confused because I thought the point of the initializer list is to avoid implicitly calling the default constructor for member variables, but it still seems to be trying to call A's default constructor.
Any explanation is appreciated, thanks.
edit: after more messing around, it seems like it complies properly if B does not inherit from A. Still unsure why inheriting from A results in A's default constructor being called from B's constructor.
Since B is derived from A, every B is an A. That means to construct a B, you must also construct an A. However, you do not tell B's constructor how to construct an A, so the default constructor is used.
If you want B to be derived from A and only hold a shared_ptr to A, then A must not do anything you don't want B to do. Here, A has _x and _y.
It's not clear what you really want, but perhaps you want some other base class that both A and B derive from that only has what both A and B should have.
The classic example of inheritance in C++ is something like Instrument being the base class that has members like Play with derived classes like Trumpet and Clarinet having the thing that makes some particular instrument a trumpet. Only what is common to Trumpets and Clarinets should be in Instrument.
When you call B b(a);, you construct a B object using the constructor B::B(std::shared_ptr<A> a).
The issue is in your definition of this constructor. B inherits from A, meaning that B is not just a B, but instead is really an A and B stacked on top of each other. A is the base class, so it is on the bottom. So when you try to construct a B object, the code must first construct the A object at the bottom/base to form the foundation for the B object to exist on. That means that you actually have to tell the code how to construct the A object.
Because you defined a constructor for A that takes two int variables, the compiler does not generate a default constructor for A. Therefore, you must explicitly write out how A should be constructed within B. Constructing the A object can be done in the initializer list of the B object's constructor:
B::B(std::shared_ptr<A> a) : A(0,0), _a(a) {}
I have been trying to figure out how to forward declare classes across multiple files in C++. I was able to successfully do it with two classes, but doing this across many classes puzzled me. I tried forward declaring all the classes in a header file and including that in all the classes, but I got the error of incomplete classes. I looked into it, but all the solutions seemed unreasonable or confused me. Can you please explain a good way to do it.
If it helps here is some example code of the issue that specifically occurring. Class A is included in Class C, but Class A also includes Class B which holds Class C resulting in an error because Class C has not been declared.
Class Forward Declaration
//Tried "Class Name {};" but that also failed
Class A;
Class B;
Class C;
Class A
//Class A
#include "B.h"
class A{
private:
B b;
public:
void SetBInt(int set) {b.SetInt(set);}
}
Class B
//Class B
#include "C.h"
class B{
private:
C c;
int i = 0;
public:
void SetInt(int set){i = set;}
}
Class C
//Class C
#include "A.h"
class C{
private:
int i = 0;
public:
void SetInt(int set){i = set;}
}
You have to avoid circular dependencies. One common way to avoid them is by pre-declaring the type, and not having any instances or function calls of that type in the header.
You do this by changing instances, such as B b, into references or pointers: B* b. You also have to move any code that uses b into the CPP file, so you can #include "B.h" prior to using it.
For example, instead of
// we'll remove this header's dependency on B shortly
#include "B.h"
class A
{
B b;
public:
A() { b.SetInt(0); }
};
You do something like this:
class B;
class A
{
B *b; // *pointers and &references to a predeclared class are fine.
public:
A();
~A();
};
... and then in A.cpp:
#include "A.h" // ALWAYS include your own header first
#include "B.h"
A::A()
{
// we didn't need to know how big B was until now, when we're about to make one and
// run its constructor. We'll also need to know what functions are available, and the
// types of all its parameters (or lack of parameters).
b = new B();
b->SetInt(0);
}
A::~A()
{
delete b; // for every "new" there must be a "delete"
}
Yes, this would be (much) better with std::unique_ptr<B> b instead of a raw pointer. With a smart pointer we wouldn't need an explicit destructor. I just didn't want to throw too much potentially new stuff at someone still learning.
Alternatively, you could pass a reference into the constructor, and use the member initializer list (you can only set references when they're constructed). This raises problems with "Object Lifetime". If the instance of B you pass in at construction time is destructed before A is done with it, you're program will violently crash (if you're lucky: that way you'll have a good idea of what the problem is) the next time it's used. Best to avoid it till you have considerably more experience under your belt.
Update
The actual context is that I need to create a package to submit to NIST, trying to test a Facial Recognition Algorithm I am working on. The API to use can be found at NIST API and the project to git is at git project
Some code to make a summary of the scenario:
a.h - interface A, composed by pure virtual methods and one static method (frvt11.h at NIST project)
class A {
public:
virtual ~A() {}
virtual void pure_virtual_method_a() = 0;
virtual void pure_virtual_method_b() = 0;
static int static_method();
}
b.h - header file for b.cpp, where interface A's methods are implemented
#include "a.h"
class B : A {
public:
void pure_virtual_method_a();
void pure_virtual_method_b();
static int static_method();
}
b.cpp - Implementation of interface A's methods.
#include "b.h"
void pure_virtual_method_a() {/*implementation*/};
void pure_virtual_method_b() {/*implementation*/};
int static_method() {/*implementation*/};
c.cpp - A file with only a main method and where I want to instantiate an object of B to use its methods.
#include "b.h"
int main(){
B obj;
obj.pure_virtual_method_a();
return 0;
}
Question 1: To instantiate an object of B in c.cpp, do I need to write the header file b.h like above? That seems to be so redundant! It looks like interface A is so unnecessary :-(
Question 2: Is the code presented the right way to implement interface A, and use an object of type B?
Question 3: Do I need to declare a constructor for B in b.h and implement it in b.cpp?
Question 1
You miss a semicolon after the closing curly brace, and it is better to specify that the pure virtual methods you implement in B are marked as override. This allows the compiler to emit warnings in case you forget to change any of the overridden method declarations as soon as the corresponding pure virtual methods in A would change. Thus you will end up with:
#include "a.h"
struct B : public A {
void pure_virtual_method_a() override;
void pure_virtual_method_b() override;
static int static_method();
};
From this it is also clear that for the compiler to be able to declare B as a type, A needs to be declared as well. For example, how would the compiler check the override keyword if it did not yet already have a declaration of A. In case you would not have any overridden virtual methods, A still needs to be known, since the compiler needs to be able to deduce the size of B.
Furthermore, as mentioned in the comments, declaring B as a struct allows you to drop the public keyword, since the default visibility of a struct is public in contrast with private default visibility for a class. This is the only difference between classes and structs in C++. Thus, for interfaces, using structs is more natural.
Question 2
Not completely. b.cpp should look something along the following lines:
#include "b.h"
void B::pure_virtual_method_a() {/*implementation*/};
void B::pure_virtual_method_b() {/*implementation*/};
int B::static_method() {/*implementation*/};
Otherwise, you declare and define three methods in the global namespace, and the linker will complain about undefined references to the three methods of B declared in b.h.
Furthermore, B needs to know how to derive from A, either publicly, protected, or private.
Furthermore, it is a good idea to add include guards to the header files, to prevent the compiler from seeing the same type declaration twice when compiling an object file like a.o or b.o:
#ifndef B_H
#define B_H
#include "a.h"
struct B : public A {
...
};
#endif
Finally, static_method() needs an implementation for A as well, static methods can not be virtual.
Question 3
You do not need to implement a constructor for B necessarily. In case you do not define one, the compiler will generate a default constructor for B. However, in case you define a non-default constructor for A, you will need to define one for B in case you want to construct instances of type B. The constructor can be implemented inline in the header file, or can be defined in b.cpp.
Question 1.
You can use Factory Pattern, then u can add b.h only in Factoru files? and return pointers or smart pointer to A class. For eample, it can be factory function like:
std::unique_ptr<A> getObject(/*params*/)
{
return std::make_unique<B>(/*params*/)
}
And then in c.cpp file:
auto obj = getObject(/*params*/);
obj->pure_virtual_method_a();
Then you can create another implementations of A interface, and return them from factory.
Question 2.
should be class B : public A
and
void B::pure_virtual_method_a() {/*implementation*/};
void B::pure_virtual_method_b() {/*implementation*/};
int B::static_method() {/*implementation*/};
Question 3.
If you need constructor in class A or constructor exactly for class B, you need to define and implement B class constuctor.
I have two classes A and B, and in class A I have an member of type B:
class B {
public:
B(); //default constructor
};
class A {
public:
A(); //constructor
B b;
};
This is the definition of class A's constructor:
A::A() : b()
{}
Here, I tried to initialize b using the initialization list. My question is, is this way to initialize b correct, or am I just creating another temporary object named b inside the constructor of A that has nothing to do with A::b?
This is correct. However, since b is of class type, the default constructor will be called automatically if b isn't mentioned in A::A's initialization list, so you don't need to mention it at all.
This method will initialize the field b with the constructor B::B(). It does not create a temporary local.
Note that in this particular case it's also unnecessary. The default constructor generated for A will do this by itself. There is nothing wrong with being explicit here, it's just unnecessary
I have two classes
class a {
public:
a(int i);
};
class b {
public:
b(); //Gives me an error here, because it tries to find constructor a::a()
a aInstance;
}
How can I get it so that aInstance is instantiated with a(int i) instead of trying to search for a default constructor? Basically, I want to control the calling of a's constructor from within b's constructor.
You need to call a(int) explicitly in the constructor initializer list:
b() : aInstance(3) {}
Where 3 is the initial value you'd like to use. Though it could be any int. See comments for important notes on order and other caveats.
Use an initialization list:
b::b() : aInstance(1) {}
Just use a constructor which is defined like this:
class b {
public:
b()
: aInstance(5)
{}
a aInstance;
};
The top two answers won't work. You put class declarations in the .h header files, and (member) function definitions in the .cpp files. The braces {} that the respondents have put define the b constructor block. In practice no one would want that empty. Yet you can't define it properly in the .cpp or the compiler will report error of 'redefinition'. (As the linker would anyway if the header file is #included in several translation units) Since the purpose of header files is that they CAN be included in several .cpp's the answers above are unfeasable.
I think you should use a pointer to 'a' like:
class b {
public:
b() : aInstance(new a(5)) {}
a *aInstance;
};
This way you will have defined behaviour. Of course you will need to free *aInstance in the destructor.