I want to create a class object, which will use a different class constructor depending on the given parameter. This is what I've tried so far.
class A{
public:
A(int x){
if (x == 1){
B(); //Initialize object with B constructor
else {
C(); //Initialize object with C constructor
}
}
};
class B : public A{
public:
B(){
//initialize
}
};
class C : public A{
public:
C(){
//initialize
}
};
int main(){
A obj(1); //Initialized with B constructor
return 0;
}
In a word, you can't do this in C++. The typical solution is to look towards the factory pattern.
class A {
public:
virtual ~A() {}
A() = default;
};
class B : A {
public:
B() = default;
};
class C : A {
public:
C() = default;
};
enum class Type
{
A,
B,
C
};
class Factory
{
public:
A* operator (Type type) const
{
switch(type)
{
case Type::A: return new A;
case Type::B: return new B;
case Type::C: return new C;
default: break;
}
return nullptr;
}
};
int main()
{
Factory factory;
A* obj = factory(Type::B); //< create a B object
// must delete again! (or use std::unique_ptr)
delete obj;
return 0;
}
Related
I have 2 classes lets say Class A and Class B,
class A {
public:
A(B b);
B GetB();
private:
B b;
};
class B {
public:
B();
void IncrementCounter();
int GetCounter();
private:
int counter = 0;
};
I want to pass an object of type B to class A's constructor and then save this instance of class B in Class A instance.
What is the best way to pass class B instance as a parameter, and what is the best way to save class B instance in class A instance.
Note: I do not want to create copies of class B instance, I want A.getB().GetCounter to always be the same as b.GetCounter().
int main(){
B b;
A a(b);
b.IncrementCounter();
a.getB().IncrementCounter();
// then b.GetCounter() is same as a.getB().GetCounter() and both = 2
}
I see people using pointers/smart pointer and references/std:reference_wrapper, what is the difference?
Use std::shared_ptr if you don't want copies, example :
I assume you are familiar with references, const references and const member functions.
#include <memory>
#include <iostream>
class B
{
public:
B()
{
number_of_instances++; // keep track of number of instances of class B
}
void IncrementCounter()
{
counter++;
}
int GetCounter() const
{
return counter;
}
int NumberOfInstances() const
{
return number_of_instances;
}
private:
int counter{ 0 };
static int number_of_instances;
};
class A
{
public:
A(const std::shared_ptr<B>& b) :
m_b{ b }
{
}
// return a reference to the object shared_ptr m_b points to
B& GetB()
{
return *m_b;
}
// return a const reference to the object shared_ptr m_b points to
const B& GetB() const
{
return *m_b;
}
private:
// https://en.cppreference.com/w/cpp/memory/shared_ptr
std::shared_ptr<B> m_b;
};
int B::number_of_instances{ 0 };
int main()
{
auto b = std::make_shared<B>();
b->IncrementCounter();
A a1(b);
A a2(b);
std::cout << "number of instances of B = " <<b->NumberOfInstances() << "\n";
std::cout << "shared_ptr<B> reference count = " << b.use_count() << "\n";
std::cout << a1.GetB().GetCounter();
return 0;
}
Note: I do not want to create copies of class B instance, I want A.getB().GetCounter() to always be the same as b.GetCounter().
Then you need to make A store a B& reference instead of a B object instance, eg:
class A {
public:
A(B& b);
B& GetB();
private:
B& b;
};
A::A(B& b) : b(b) {
}
B& A::GetB() {
return b;
}
As long as the B object outlives the A object (which it does in your example), you will be fine, no (shared) pointers will be needed.
However, since you are declaring A before B, you can't use B at all in A as you have shown. The compiler won't know what B is while parsing A.
Since B doesn't depend on A for anything, you can simply swap the order of their declarations, eg:
class B {
public:
B();
void IncrementCounter();
int GetCounter();
private:
int counter = 0;
};
class A {
public:
A(B& b);
B& GetB();
private:
B& b;
};
Otherwise, if that is not an option for your situation, then you will have to use a forward declaration of B before declaring A, eg:
class B; // <--
class A {
public:
A(B& b);
B& GetB();
private:
B& b;
};
class B {
public:
B();
void IncrementCounter();
int GetCounter();
private:
int counter = 0;
};
Forward declaration only work when dealing with references and pointers, not with instances.
class D {
public:
void HelloWorld(){cout << "Hello" << endl;}
};
class B {
public:
void SetCallBack(std::function<void()> callback) {
callback_ = callback;
}
private:
std::function<void()> callback_;
};
class A {
public:
A(B *b) : b_(b) {}
std::function<void()> Helper(){
return [](){d_->HelloWorld(); };
}
private:
B *b_;
std::unique_ptr<D> d_;
};
class C {
public:
C(std::unique_ptr<B> b, std::unique_ptr<A> a)
: b_(std::move(b)),
a_(std::move(a)) {
b_->SetCallBack(a_->Helper());
}
private:
std::unique_ptr<B> b_;
std::unique_ptr<A> a_;
};
Questions:
When B holds a copy of A's member function, does it mean B also holds a pointer to A?
Given A's constructor depends on B, B has to be declared first in C and destructed later. But is this a buggy code that A also depends on B and when A is destructed if B calls the callback, what happens?
My question is very similar like other's, but a bit different. I have a sample code:
class B1 {
private :
int * ptr;
public:
B1() : a{ 1 } { ptr = new int{ 2 }; }
B1(const B1& other) : a{ other.a } { ptr = new int{ *other.ptr }; }
~B1() { delete ptr; }
int a;
virtual void smthing() = 0;
};
class D : B1 {
public:
D(int i) : B1{} {}
D(const D& a) : B1{ a } {}
void smthing() { return; };
};
int main() {
D d { 3 };
D dd { d };
return 0;
}
I am using vs2015, and this code is works, but gives me error: object of abstract class type "B1" is not allowed...
If I remove this line D(const D& a) : B1{ a } {}, the base class copy constructor is called and there's no problem, but if I need the derived class copy constructor how can I make this work without error?
Thanks for the answer!
This question already has answers here:
C++ Call Pointer To Member Function
(4 answers)
Closed 5 years ago.
A have a lot of B classes, a class A has one object b. This object b has a function (calc) that needs a pointer to a method in an object of A. This method (fun) acess private variables in class (in my example just return 3).
class A;
class B {
public:
virtual int calc ( int (A::*fun)()) { return 2*fun(); };
};
class A {
B* b;
public:
A (B* b_) : b (b_) {};
int fun() { return 3; };
int run(){ return b->calc(&A::fun); };
};
int main() {
B* b = new B();
A a(b);
a.run();
return 0;
}
How can I use a pointer to a method correctly in definition of calc method in class B?
I am getting this error message:
teste.cpp:10:58: error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘fun (...)’, e.g. ‘(... ->* fun) (...)’
virtual int calc ( int (A::*fun)()) { return 2*fun(); };
^
I recommend the std::function approach if it's feasible for you. However, for the sake of completeness, here's how you would correctly use pointer-to-member functions.
The pointer-to-member itself doesn't store the "current" instance of A, so you need to pass that explicitly. Then you use the special ->* (or .*) syntax to call it.
virtual int calc (A* value, int (A::*fun)()) {
return 2 * (value->*fun)();
};
Then you would call it as b->calc(this, &A::fun);.
You can do it your way, but the member function must be called on a particular instance:
class A;
class B {
public:
virtual int calc(A* a, int (A::*fun)()) { return 2 * (a->*fun)(); };
};
class A {
B* b;
public:
A(B* b_) : b(b_) {};
int fun() { return 3; };
int run() { return b->calc(this, &A::fun); }; // now also passing this pointer
};
int main() {
B* b = new B();
A a(b);
a.run();
return 0;
}
If you can live without calc() being virtual then a lambda is also an option:
class A;
class B {
public:
template<typename T>
int calc(T fun) { return 2 * fun(); };
};
class A {
B* b;
public:
A(B* b_) : b(b_) {};
int fun() { return 3; };
int run() {
return b->calc([this]() {return fun(); } );
};
};
int main() {
B* b = new B();
A a(b);
a.run();
return 0;
}
A pointer-to-class method is defined and initialized as (assuming SomeFn matches the signature):
RetType (ClassName::*pfn)(Args) = &ClassName::SomeFn;
And is called as:
ClassName * ptr = GetClassPtr();
(ptr->*pfn)(arg, arg);
If you are able to use C++11, then you should use std::function and std::bind: Otherwise you need to use a pointer to member function + a pointer to the instance.
With C++11
#include <functional>
class B {
public:
virtual int calc (std::function<int()>&& fun) { return 2 * fun(); }; };
};
class A {
B* b;
public:
A (B* b_) : b (b_) {};
int fun() { return 3; };
int run() { return b->calc(std::bind(&A::fun, this)); };
};
Without C++11
class B {
public:
virtual int calc (int(A::*fnptr)(), A* a) { return 2 * (a->*fnptr)(); };
};
class A {
B* b;
public:
A (B* b_) : b (b_) {};
int fun() { return 3; };
int run() { return b->calc(&A::fun, this); };
};
See example here.
class A;
{
private:
int a;
public:
virtual int getV() { return a; }
} a;
class C : public A;
{
private:
int c;
public:
int getV() { return c; }
} c;
class D
{
public:
A* liste;
} d;
Memory for liste may be allocated and A::a and C::c are holding values. Now if I put c in D::liste[0] and give it out with
cout << d.liste[0].getV();
it prints A::a. Why doesn't it print out C::c although I declared A::getV() as virtual?
C++ polymorphism works only for pointers and references. liste[0] has type A, not A* or A&, so the liste[0].getV() call is not dispatched virtually. It just calls A::getV().
I wrote the program like this and getting the correct result as expected
#include <iostream>
using namespace std;
class A
{
private:
int a;
public:
virtual int getV() { cout<<"A";return a; }
};
class C : public A
{
private:
int c;
public:
virtual int getV() { cout<<"C";return c; }
};
class D
{
public:
A* liste[2];
};
int main()
{
D d;
d.liste[0]=new C();
d.liste[1]=new A();
cout<<d.liste[0]->getV();
return 0;
}
Just have a look at it..