I have class A with constructor A(int a)
A.h
calss A{
public : A(int a);
}
A.cpp
#include "a.h"
#include <iostream>
A::A(int a)
{
std::cout<<a<<end;
}
I need to initialize this class from another class B,
I tried
B.h
class B{
public : B();
A tmp;
//A tmp(4); //this giving syntax error
}
and
B.cpp
B(){
tmp = A(4);
}
But I am getting compiler error "error: no matching function for call to 'A::A()'"
The problem is that A doesn't have a default constructor (because if you define another constructor and default one is not generated) and so A objects cannot be default constructed.
The solution is to use constructor initialization lists for every constructor of B where you call the appropriate constructor for tmp.
class B {
A tmp;
public:
B() : tmp(4) {}
};
If you can use c++11 and in every (or at least most of the) constructors of B you create tmp the same way you can use:
class B {
A tmp{4};
public:
B() {};
}
Constructors should not have a return type. Remove the void in the declaration and you should be good to go. Same goes for your class B.
Constructors are special member functions without any return type.
//A tmp(4); //this giving syntax error
This will for sure give you an error because you mentioned
void A(int a)
and this is not constructor; because its has return type (void).
when you explicitly define parametrized constructor (like A(int a) )the default constructor gets vanished and for this statement
A tmp;
to compile you have to provide your own default constructor.
It would be great always to post complete error message.
Rather than getting "no matching function for call to" , I am sure that you will be getting below error:
error: no matching function for call to ‘A::A()’
note: A::A(int)
This clearly indicates that default constructor A::A() is missing from your code as you have provided your own constructor.
Suggestion: You have defined conversion constructor. It is good practice to use "explicit" keyword.
*.h file
class A
{
public:
A(int a);
};
class B
{
public:
B();
A *tmpA;
};
*.cpp file
A::A(int a)
{
MessageBox(NULL,L"",L"", MB_OK);
}
B::B()
{
tmpA = new A(4);
}
usage
{
B *b = new B();
}
is it correct for you?
Related
I am writing code that follows the member dependency schemes discussed in:
Resolve build errors due to circular dependency amongst classes
In it's simplest form, the code headers looks like this:
A.h
class B;
class A{
public:
A();
void send(int i);
B* b;
};
B.h
#include A.h
#include foo.h
class B : public foo{
public:
B(A *a);
A *a;
void send(int i); //this invokes a member function of a
};
Now, in my source code, if I use an initializer list that looks like:
A.cpp
A::A() : b(this){};
I get a compiler error saying "error: cannot convert ‘A* const’ to ‘B*’ in initialization
However, if I don't use an initializer list, and instead I use a new pointer declaration, it compiles fine:
A::A(){
b = new B(this);
}
Could anyone help me reason why the initializer list causes the compiler to misinterpret the class B constructor argument? Or maybe something else is happening?
Just in case it helps, here is the B.cpp file:
B.cpp
#include "B.h"
#include "A.h"
B::B(A *inst){
a = inst;
}
void B::send(int i){
a->send(i);
}
In your assignment:
b = new B(this);
you are constructing a B object from this, and assigning a pointer to this object to b. You need to do the same thing in your member initializer list:
A::A() : b(new B{this}){};
First, let's remove the noise and minimize your example:
struct A;
struct B { B(A*) {} };
struct A {
A() : b(this) { }; // error: cannot convert 'A*' to 'B*' in initialization
B* b;
};
int main() {}
The data member b of A is of of type B* rather than B, and we can minimize the example even further:
struct A {};
struct B { B(A*) {} };
int main() {
A a{};
A* pa = &a;
B* pb{pa}; // error: cannot convert 'A*' to 'B*' in initialization
}
The error message is now quite explanatory (given the simple context): we simply cannot
initialize a pointer to B by a pointer to A.
The constructor of B is not relevant here, as it provides a way to:
initialize an object of type B by a pointer to A.
The new operator, however, dynamically creates object and returns a pointer to it, meaning that the following:
B* pa{new B(pa)};
is:
initializing a pointer to B by a pointer to B which points to an object of type B which was initialized by a pointer to A.
Is there some way to initialize(?) member variable c of type C in the first part of the below example? Or must I use the new() method shown in the second part of the example?
Class B takes class A as an injected dependency. So does class C. Class B is additionally composed of class C.
How do I get the injected A to B's member C?
Part 1
class A { // ...; };
class C {
public:
C(A &a) : a(a) {} // constructor
};
// Does not work as is. Want to make compiler manage C lifetime.
class B {
public:
B(A &a); // constructor
C c(a); // member variable
};
// constructor
B::B(A &a) : a(a) {
}
Part 2
// Works, but requires programmer to manage C's lifetime.
class B {
public:
B(A &a); // constructor
C *c; // member variable
};
// constructor
B::B(A &a) : a(a) {
c = new C(a);
}
Several good answers below! My apologies for the confusing example. I have up-voted all of the good answers and questions. Unfortunately I can only mark one answer as the accepted answer, so I am choosing the first one which gave me the "ah-ha" moment in which I saw the solution to my real problem, which was more complex than my lame example here.
Member variables are initialized in constructor's initialization list (before body) so you need to do that:
B::B(A &a)
: c(a) // Calls constructor C(a) on member c
{}
You almost have it:
class B {
public:
B(A &a);
C c(a); //see note 1
};
B::B(A &a) : a(a) { //see note 2
}
Note 1:
There are two problems with C c(a); here:
a is not in scope. a only exists within the scope of the constructor, so c needs to be initialized from there.
Until C++11, non-static data member initializers (NSDMIs) were prohibited. Even in C++11, though, you must use an equals sign (C c = value;) or braces (C c{value};) when initializing an NSDMI.
Note 2:
You've almost got this right:
B::B(A &a) : a(a)
You're trying to initialize a data member called a with the argument given to the constructor. You actually want to initialize c like this, not a non-existent a:
B::B(A &a) : c(a)
The lifetime of c will be that of the instance of the B class. Using dynamic memory management is certainly not necessary.
"How do I get the injected A to B's member C?"
You can do so using B's constructor member initializer list
class B {
public:
B(A &a) : c(a) {
// ^^^^
}
C c; // <<< It's not possible to initialize members in their
// declaration.
};
The following:
C(A &a) : a(a) {}
will not compile since a (the first a in the initialization list) is not a member variable of C.
Same applies to the constructor of B.
I'm not used to c++ and I'm having a problem writing a constructor.
See this example, is a short version of the code I'm working on:
class B {
public:
B(int x);
}
class A {
public:
B b;
A(){
// here I have to initialize b
}
}
That throws a compiler error since I need to initialize b in A's constructor because B does not have a default constructor.
I think I have do it in the initialization list, but the B(int x) argument is a value I have to calculate with some algorithm, so I don't know how this should be properly done, or if I'm missing something or doing it wrong.
In other language like java I would have a reference to B and initialize it inside the A's constructor after the other code I need to get the value for the initialization.
What would be the right way to initialize b in this case?
Thanks!
You can invoke functions in your constructor initializer list
class B {
public:
B(int x);
}; // note semicolon
class A {
public:
B b;
A()
:b(calculateValue()) {
// here I have to initialize b
}
static int calculateValue() {
/* ... */
}
}; // note semicolon
Note that in the initializer list, the class is considered completely defined, so you can see members declared later on too. Also better not use non-static functions in the constructor initializer list, since not all members have yet been initialized at that point. A static member function call is fine.
You use an initializer list, something like this:
A() : b(f(x)) {}
#include<iostream>
class B {
public:
B(){} // A default constructor is a must, if you have other variations of constructor
B(int x){}
}; // class body ends with a semicolon
class A {
private:
B b;
public:
A(){
// here I have to initialize b
}
void write(){
std::cout<<"Awesome";
}
};
int main(){
A a;
a.write();
}
In C++, if you have a constructor that takes an argument, a default constructor is a must, unlike other languages as Java. That's all you need to change. Thanks.
How come, when setting up class composition, contained classes can be called with a default constructor but not with one that takes parameters?
That's kind of confusing; let me offer an example.
#include "A.h"
class B
{
private:
A legal; // this kind of composition is allowed
A illegal(2,2); // this kind is not.
};
Assuming both the default constructor and one that takes 2 integers exists, only one of these is allowed. Why is this?
It is allowed for sure, but you just need to write it differently. You need to use the initializer list for the composite class's constructor:
#include "A.h"
class B
{
private:
A legal; // this kind of composition is allowed
A illegal; // this kind is, too
public:
B();
};
B::B() :
legal(), // optional, because this is the default
illegal(2, 2) // now legal
{
}
You can provide constructor parameters, but you are initialising your members wrong.
#include "A.h"
class B
{
private:
int x = 3; // you can't do this, either
A a(2,2);
};
Here's your solution, the ctor-initializer:
#include "A.h"
class B
{
public:
B() : x(3), a(2,2) {};
private:
int x;
A a;
};
a class declaration does NOT initialize the members which compose the class. hence, the error when you are trying to constrcut an object inside the declaration.
member initialization takes place inside the constructor of a class. so you should write:
#include "A.h"
class B
{
public:
B();
private:
A a;
};
B::B() :
a(2,2)
{
}
class A{
A(int a = 5){
DoSomething();
A();
}
A(){...}
}
Can the first constructor call the second one?
Not before C++11.
Extract the common functionality into a separate function instead. I usually name this function construct().
The "so-called" second call would compile, but has a different meaning in C++: it would construct a new object, a temporary, which will then be instantly deleted at the end of the statement. So, no.
A destructor, however, can be called without a problem.
Not before C++0x, no.
BUT, just out of academic interest I've come up with a really horrible way* to do it using a placement operator "new" (someone care to point out how portable this is?)
#include <new>
#include <iostream>
class A
{
public:
A(int i, int j)
: i_(i), j_(j) { }
A(int i)
{ new (this) A(i, 13); }
int i_,j_;
};
int
main() {
A a1(10,11), a2(10);
std::cout
<< a1.i_ << ", "
<< a1.j_ << std::endl
<< a2.i_ << ", "
<< a2.j_ << std::endl;
return 0;
}
*Hell no, I don't write this in the production code.
The answer is in fact "yes", but as others have suggested, it doesn't do what you want. You can of course use the constructor of a base class, either implicitly or explicitly:
struct B {
B() {}
B( int x ) {}
};
struct A : public B {
A() {} // calls B() implicitly
A( int a, int b ) : B( b ) {} // calls B(int) explicitly
};
Not directly. There are a few ways to work around this.
From the initializer list of your class' constructor, you can call a constructor on any base class, and on all member variables.
So you can usually refactor your class and split it into several smaller ones to solve the problem. The commonly executed code can be placed in a member object or perhaps a base class. Then each of the main class' constructors just have to decide which construcotr to use to initialize that member.
class B {
B() { }
B(int b) { DoSomething(); }
}
class A{
A(int a = 5) : b(a) { } // call B's constructor which does something
A() : b() {} // call B's constructor which does nothing
B b;
};
This is an old question; however,
class A{
A(int a = 5){
DoSomething();
A();
}
A(){...}
}
could be
class A{
A(int a = 5){
*this = A();
DoSomething();
}
A(){...}
}
As pointed out by Pavel Radzivilovsky in his answer, since C++ 11, it is possible. It is the same syntax as for explicitely calling the parent's class constructor from a child class. This is useful when a class needs to have multiple constructors (say, a default constructor and a constructor with attribute initialization) but some operations have to be done in all cases. This allows to avoid code repetitions.
Here is an example:
class A
{
public:
A()
{
foo();
}
A(Attribute attribute) : A()
{
this->attribute = attribute;
}
//------ some other code --------
private:
Attribute attribute;
void foo()
{...}
//------ some other code -------
};
In this simple example, I assume that the function foo() needs to be called in all cases for the object to be correctly initialized. With this syntax, if the second constructor (with attribute initialization) is called, it will first perform the operations in the default constructor before executing the instructions in the attribute-initialization constructor.
It can also be done the other way around: the default constructor can call another constructor with default parameters.
Before C++ 11, it was necessary to duplicate the common instructions of all constructors or define methods that do the actual object initialization.