I have two classes which represent two different data types that can be converted back and forth. I want to have a constructor for each which takes an object of the other type so that I can more easily convert between the two, like so:
class A{
public:
A(B n){
//Do stuff converting n to type A
}
};
class B{
public:
B(A n){
//Do stuff converting n to type B
}
};
But it always fails to compile.
If you pass B by reference, you can use it as an incomplete type in A, with a forward declaration, like:
class B; // forward declaration
class A {
public:
A() = default;
A(B& n); // declare it here
};
class B {
public:
B() = default;
B(A n) {
//Do stuff converting n to type B
}
};
A::A(B& n) // define it here, B is fully visible now
{
//Do stuff converting n to type A
}
int main()
{
A a;
B b(a);
A another(b);
}
Note that you'd also need default constructors for at least A or B, as otherwise you cannot create an A without a B or the other way around. We also only declared the constructor in A, but defined it after B is fully visible (thanks #MattMcNabb for the comment). In this way, you'd be able to use any member of B in the constructor, since at that point B is fully visible.
The problem you are having is a common for beginners of C++ (or C for that matter).
The issue is that the signature A(B n) is seen by the compiler before the declaration of B is seen. But clearly, you cannot put B before A in the code, or you'd end up with the same type of situation.
This can be solved using forward declarations and references. My suggested default approach to this would be to declare these two entities as
class B;
class A {
public:
A(const B& n) {
// Do stuff converting n to type A
}
};
class B {
public:
B(const A& n) {
// Do stuff converting n to type B
}
};
Related
I've run into a bit of a chicken and the egg scenario.
Say I have these two classes
class A{
public:
A(B& );
private:
B& ref;
};
class B{
public:
B(A& );
private:
A& ref;
};
Is there any way for me to initialize them? Because the fields are references, I have to bind them in the member initializer list so they can never be null. However, I can't make either one of them without the other, so I can't even supply the references.
Currently, I have two thoughts. The first is that I can switch one of the fields to a raw pointer, that way I can just supply a nullptr and bind it later in a method. However this weakens my null safety so I don't really want to do that. My second thought was that I could just declare a variable without initializing it, so something like
A foo;
B bar(foo);
foo(bar);
where I just construct it later. Unfortunately, this calls a default constructor on the first line, which isn't provided, so this doesn't work.
So I would like some advice on getting my current ideas to work, or if there's a built-in mechanism in C++ for this that I don't know about.
Its a chicken and egg problem. You need an A to create a B and you need a B to create an A.
However, if you always create an A and a B together, then I would suggest, as already mentioned in a comment, to wrap them in a class. Then you can use the member initializer list:
struct B;
struct A {
A(B& b) : ref(b) {}
B& ref;
};
struct B {
B(A& a) : ref(a) {}
A& ref;
};
struct AB {
A a;
B b;
AB() : a(b),b(a) {}
};
Using the reference to member b before it has been initialized is fine as long as A only stores the reference and does not read from it or call methods.
However, once they are wrapped in the same class it is kind of pointless to have them store references to each other.
Moreover reference members have certain unpleasant implications (eg no copies). Consider if thats what you really like or if perhaps pointers are fine.
If you are trying to create a loop dependency then at least one of the members will need to be a pointer. But it is otherwise fully possible to have this work by using forward declarations.
class B;
extern B b;
class A
{
public:
A(B & b)
: b(b)
{
}
private:
B & b;
};
class B
{
public:
B(A & a)
: a(a)
{
}
private:
A & a;
};
A a(b);
B b(a);
I was looking to create a function that is capable of working with any Derived Object of A.
However in this example, I can't seem to be able to use B Object in a function that has a A Typing on it. Is there any way I pass B into the Function?
class A {
public:
A() {
}
};
class B :A {
public:
B() {
}
};
void function(A a) {
return;
}
int main(void) {
B b();
function(b);
}
I've commented on the fixes needed inline:
class A {
public:
A() {}
};
class B : public A { // public inheritance or A will be an inaccessible base of B
public:
B() {}
};
void function(const A& a) { // take a reference to an A to avoid copy-slicing
// ... work with the A part of the object you reference with `a`
}
int main() { // void not needed (but not an error as such)
B b; // not a function declaration anymore
function(b);
}
Actually you are lucky. You made two mistakes that caused passing b to the function fail, while in fact without that other mistakes you can pass b to the function but it would do the wrong thing silently.
First the two mistakes: B b(); declares a function. To declare a default constructed B you write B b;. Then B inherits privately, hence you cannot convert a B to an A. Thats what the error your code causes have told you.
However, after fixing those (and removing user declared constructors taht shouldnt be there when they do nothing)...
class A {};
class B : public A {};
void function(A a) {}
int main(void) {
B b;
function(b); // object slicing !!
}
This code compiles without errors, but usually it does the wrong thing!
Any B can be converted to an A because the inheritance is public, but what happens is object slicing: What is object slicing?. If B had any members not in A then they would all be lost when passing it to function. Its not an issue here because neither A nor B have any members, but in general you want to avoid objects to get sliced.
TL;DR: References / pointers are needed for polymorphism. Pass by (const) reference:
void function(const A& a) {} // does not modify a
void function(A& a) {} // modifies a
i'm working with c++.
I need to create two classes that refering to each other.
Something like this:
class A {
private:
B b;
//etc...
};
class B {
private:
A a;
//etc...
};
How can i do that?
Sorry for my bad English and thanks you for helping me :)
You can't do that even in principle, because a single A object would contain a B which contains another A, which contains another B and another A ...
If you just want a reference, you can simply do
class B; // forward declaration
class A {
B& b_; // reference
public:
explicit A(B& b) : b_(b) {}
};
class B {
A a_;
public:
B() : a_(*this) {}
};
Now each B contains an A which refers to the B in which it sits.
Do note however that you can't really do anything with b (or b_) inside A's constructor, because the object it refers to hasn't finished creating itself yet.
A pointer would also work - and of course A and B can both have references instead of B containing an immediate object.
One of the corner stones of OOP is reusing code instead of repeat it over and over. Thus, your projects shorten and get more readable.
C++ gives you all the tools you need to reuse methods instead of repeating the code. Although when it comes to constructors I do not know how to reuse them.
I am not talking of heritage or how to send a message to the father. I am talking about reusing the constructor of the class itself.
The analogy in JAVA is something like this:
public Foo() {
this(0,0,0);//Not needed in this case, just to clarify
}
public Foo(Foo f){
this(f.getA(), f.getB(), f.getC());
}
public Foo(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
My question is, is there any syntaxis in C++ that allows you to do so?
C++11 has added constructor delegation and constructor inheritance.
To inherit constructors, a using-declaration is required:
class Base { ... };
class Derived : public Base
{
using Base::Base;
};
To delegate, use the ctor-initializer, but specify another constructor in the same class, instead of any subobjects (all base and member subobjects will be initialized by the constructor delegated to):
class Another : public Base
{
int member;
Another(int x)
: Base(), member(x) // non-delegating constructor initializes sub-objects
{}
Another(void)
: Another(5) // delegates -- other constructor takes care of Base and member
{}
};
And perfect forwarding can also come in handy.
Others already answered about C++11, but for C++03 there's a possible workaround: using a base class with needed constructor(s).
struct foo_base {
foo_base(int a, int b, int c) : a(a), b(b), c(c) { }
int a, b, c;
};
struct foo : foo_base {
foo() : foo_base(0, 0, 0) { }
foo(const foo& other) : foo_base(other.a, other.b, other.c) { }
foo(int a, int b, int c) : foo_base(a, b, c) { }
};
Of course, you need to consider whether it's worth the boilerplate for your purposes.
The generally accepted soultion for current compilers is to do this:
class Bar{
pubilc:
Foo() {
init(0,0,0);
}
Foo(const Foo &f){
init(f.getA(), f.getB(), f.getC());
}
Foo(int a, int b, int c) {
init(a,b,c);
}
private:
void init(int a, int b, int c){
this->a = a;
this->b = b;
this->c = c;
}
};
While this may seem like over kill in this example, that is only because of the simplicity of the example. In a real world application this would actually bring benefits in terms of reduction of repeated code.
OK C++11 covers what you need.
But your simple case has an easy solution:
/* This one is covered by providing default parameters see below.
public Foo() {
this(0,0,0);//Not needed in this case, just to clarify
}
This is done automatically by the compiler.
You do not need to write any code for this:
public Foo(Foo f){
this(f.getA(), f.getB(), f.getC());
}
The compiler generated version actually looks like this:
public Foo(Foo const& f)
: a(f.a)
, b(f.b)
, c(f.c)
{}
*/
// Now you can use all three methods and they work fine:
public Foo(int a = 0, int b = 0, int c = 0)
: a(a)
, b(b)
, c(c)
{}
F f1; // default construct no parameters: uses the three parameter version
F f2(f1); // Copy constructed. Generated by the compiler.
F f3(1,2,3); // Nomal constructor
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.