Suppose we have the following template class, inspired by std::shared_ptr (ignore bad memory management for simplicity):
template <class C> class shared_class {
public:
const shared_class& operator=(const shared_class& rhs) {
ptr = rhs.ptr;
refs[ptr] += 1;
return *this;
}
C* data() { return ptr; }
protected:
shared_class() {
if (ptr == nullptr)
ptr = new C;
refs[ptr] = 1;
}
shared_class(const shared_class& other) {
ptr = other.ptr;
refs[ptr] += 1;
}
~shared_class() {
if ((refs[ptr] -= 1) == 0) {
refs.erase(ptr);
delete ptr;
}
}
private:
static std::unordered_map<C*, size_t> refs;
C* ptr = nullptr;
};
template <class C> std::unordered_map<C*, size_t> shared_class<C>::refs = {};
I would like to use it in the following way:
class A_data {
protected:
int foo = 50;
friend class A;
friend class shared_class<A_data>;
};
class A : protected shared_class<A_data> {
public:
void foo(int f) { data()->foo = h; }
int foo() { return data()->foo; }
};
using namespace std;
int main(){
A a;
A b = a;
a.foo(40);
cout << b.foo(); // 40
}
This works well, but now suppose I want to create a class that inherits A, but also inherits its data, such as this:
class B_data : public A_data {
int bar = 100;
friend class B;
friend class shared_class<B_data> // Probably wrong
};
class B : public A {
int bar() {
return data()->bar(); // Error: no member 'bar' in A_data
}
}
This is a problem, because the constructor in shared_class only knows how to allocate A_data. It seems to me that I am only able to decide on one form of inheritence: either I inherit the template class like above, or I can inherit a different shared_class template, like this:
class B_data : public A_data {
int bar = 100;
friend class B;
friend class shared_class<B_data> // Now it's not wrong
};
class B : public shared_class<B_data> {
int bar() {
return data()->bar(); // Now it will work
}
}
While this works, I lose relation to the A class, and am now unable to do use A::foo, forcing me to define it in B:
class B : public shared_class<B_data> {
void foo(int f) { data()->foo = h; }
int foo() { return data()->foo; }
int bar() { return data()->bar(); }
}
Is there a (relatively elegant) way to make this work as though B inherits A while simultaneously B_data inherits A_data?
Related
For my new project, I wanted to use my previous code as framework to speed up prototyping by avoiding rewriting code. In the code below, Derived struct belongs to the new project and it requires to define a new member, MoreElaborateMember which has stuff relevant to the new project. I want to use the function, foo from the base project to make changes on MoreElaborateMember but I can't. How can I solve this problem without touching to the base code?
#include <cassert>
struct SimpleMember
{
int a;
};
struct MoreElaborateMember: SimpleMember
{
// lots of other stuff
};
struct Base
{
SimpleMember member;
};
struct Derived: Base
{
MoreElaborateMember member;
};
void foo(Base& base)
{
base.member.a = -1;
}
int main()
{
Base base;
Derived derived;
foo(static_cast<Base&>(derived));
assert(derived.member.a == -1);
return 0;
}
Have you considered composing MoreElaborateMember from SimpleMember instead of inheriting? Might be a bit of boiler plate but I think it would achieve what you want if I've understood correctly.
struct SimpleMember
{
int a;
};
struct MoreElaborateMember
{
MoreElaborateMember(SimpleMember& s)
: a(s.a)
{}
int& a;
int b;
};
struct Base
{
SimpleMember member;
};
struct Derived : public Base
{
Derived()
: Base()
, member(Base::member)
{}
MoreElaborateMember member;
};
void foo(Base& base)
{
base.member.a = -1;
}
int main(int, char**)
{
Derived derived;
derived.member.a = 13;
derived.member.b = 42;
assert(derived.member.a == 13);
assert(derived.member.b == 42);
foo(derived);
assert(derived.member.a == -1);
assert(derived.member.b == 42);
return 0;
}
You will be more comfortable if you use polymorphism.
#include <cassert>
struct SimpleMember
{
int a;
};
struct MoreElaborateMember : SimpleMember
{
// lots of other stuff
};
struct Base
{
protected:
SimpleMember member;
public:
virtual void set_member(int m) = 0;
};
struct Derived : public Base
{
MoreElaborateMember member;
virtual void set_member(int m)
{
Base::member.a = m;
member.a = m;
}
};
void foo(Base* base)
{
base->set_member(-1);
}
int main()
{
Derived derived;
foo(&derived);
assert(derived.member.a == -1);
return 0;
}
In multiple inheritance,where all the base class contains same function name with different functionality, we can access the protected function from particular base class using "::" scope resolution operator.
However, I tried something else. I created the objects of the base class in inside the child class. And tried calling the function using through object of that particular class.
But I was getting the following compiler error:
"‘void A::func(int&)’ is protected within this context."
Please let me know where did i go wrong.
#include <iostream>
using namespace std;
class A
{
protected:
void func(int & a)
{
a = a * 2;
}
};
class B
{
protected:
void func(int & a)
{
a = a * 3;
}
};
class C
{
protected:
void func(int & a)
{
a = a * 5;
}
};
class D : public A,public B,public C {
public:
int a;
A a_val;
B b_val;
C c_val;
void update_val(int new_val)
{
a = new_val;
a_val.func(a);
b_val.func(a);
c_val.func(a);
}
void check(int);
};
void D::check(int new_val)
{
update_val(new_val);
cout << "Value = " << a << endl;
};
int main()
{
D d;
int new_val;
cin >> new_val;
d.check(new_val);
}
If you want to keep your code with the base classes as having independent functionality and still remaining protected the easiest way to resolve your issue is by slightly changing the name of your protected functions and adding a public function that calls the protected members: See these class declarations for example:
class A {
public:
void func( int& a ) {
func_impl( a );
}
protected:
void func_impl( int& a ) {
a = a * 2;
}
};
class B {
public:
void func( int& b ) {
func_impl( b );
}
protected:
void func_impl( int& b ) {
b = b * 3;
}
};
class C {
public:
void func( int& c ) {
func_impl( c );
}
protected:
void func_impl( int& c ) {
c = c * 5;
}
};
class D : public A, public B, public C {
public:
int a;
A a_val;
B b_val;
C c_val;
void update_val( int val ) {
a = val;
a_val.func( a );
b_val.func( a );
c_val.func( a );
}
void check( int );
};
void D::check( int val ) {
update_val( val );
std::cout << "Value = " << a << std::endl;
}
This provides a nice public interface to call the protected member functions. This also resolves the issue of accessing the protected members. When I run your program and input a value of 5 it returns a result of 150 and works as expected.
This snippet should show you how inheritance works and when you can and can not access protected members:
class DerivedA : public Base {
public:
Base b;
void call_message() {
b.message(); // Protected Member of Base class can not be accessed
}
};
class DerivedB : public Base {
public:
void call_message() {
message(); // This works without problem!
}
};
Just as I did above one way to resolve this is by adding a public interface caller to the protected implementation.
class Base {
public:
void message() {
message_impl();
}
protected:
void message_impl() {
std::cout << "This is a protected member of Base\n";
}
};
Now you can do this:
class DerivedA {
public:
Base b;
void call_message() {
b.message(); // Accessible through public interface.
}
};
When you are in your derived class, it has access to its own ancestor methods. But it doesn't have access to your variables member protected and private methods and variables.
Redesign your code, you are trying things and contorting the other classes design for bad reasons. Francis' code is a good solution, but D doesn't need to inherit from anything.
If you don't want to create another function, you can do something like this:
#include <iostream>
using namespace std;
class A
{
protected:
void func(int & a)
{
a = a * 2;
}
};
class B
{
protected:
void func(int & a)
{
a = a * 3;
}
};
class C
{
protected:
void func(int & a)
{
a = a * 5;
}
};
class D : public A,public B,public C {
public:
int a;
void update_val(int new_val)
{
a = new_val;
this->A::func(a);
this->B::func(a);
this->C::func(a);
}
void check(int);
};
void D::check(int new_val)
{
update_val(new_val);
cout << "Value = " << a << endl;
};
int main()
{
D d;
int new_val;
cin >> new_val;
d.check(new_val);
}
This works because, this refers to the current instance of class D, and it already inherits class A, class B, class C. So you can directly access the protected functions of the respective classes.
Remember: It will not work if you have not inherited the classes.
I have a class derived from an interface and a friend class of the derived class. I want to access the members of derived class which is instantiated as interface. It looks like this:
Interface:
class AInterface
{
public:
virtual ~AInterface() = default;
virtual void set(int a) = 0;
};
Derived class A with friend class B:
class B;
class A : public AInterface
{
public:
~A() override {}
void set(int a) override
{
mem = a;
}
private:
friend class B;
int mem = 0;
};
class B:
class B
{
public:
B()
{
a = new A();
a->set(3);
}
int get_a()
{
// Access mem since it's a friend class
return a->mem;
}
private:
AInterface *a;
}
main:
int main()
{
B *b = new B();
std::cout << b->get_a() << std::endl;
return 0;
}
The program does not compile saying AInterface has no member named 'mem'.
Do I need getter functions in the interface and implement it in A to achieve this or is there any other way to do it?
Now work
#include <iostream>
using namespace std;
class AInterface
{
public:
virtual ~AInterface() = default;
int getMem() { return mem; }
virtual void set(int a) = 0;
protected:
int mem = 0;
};
class A : public AInterface
{
public:
~A() override {}
void set(int a) override
{
mem = a;
}
};
class B
{
public:
B()
{
a = new A{};
a->set(3);
}
int get_a()
{
// Access mem since it's a friend class
return a->getMem();
}
private:
AInterface *a;
};
int main()
{
B *b = new B();
std::cout << b->get_a() << std::endl;
return 0;
}
Method which is override by child and is pure, should be virtual.
If each class (child) Interface, variable int mem should be protected in interface.
Now works fine, like you want.
Add getter getMem()
Version with friend
#include <iostream>
using namespace std;
class AInterface
{
public:
virtual ~AInterface() = default;
virtual void set(int a) = 0;
protected:
friend class B;
int mem = 0;
};
class A : public AInterface
{
public:
~A() override {}
void set(int a) override
{
mem = a;
}
};
class B
{
public:
B()
{
a = new A{};
a->set(3);
}
int get_a()
{
// Access mem since it's a friend class
return a->mem;
}
private:
AInterface *a;
};
int main()
{
B *b = new B();
std::cout << b->get_a() << std::endl;
return 0;
}
In your class B.
class B
{
//...
int get_a()
{
return a->mem; // but a is a AInterface* !!!
}
private:
AInterface *a; // That's not an A*, but an AInterface*
};
You have 2 options.
use dynamic_cast<>
int B::get_a()
{
A* p = dynamic_cast<A*>(a);
if (p)
return p->mem;
// a is not an A*, it's another AInterface*-type object !!!
// What should you do?
throw something_or_other(); // throw?
return -1; // return an error code?
}
// or maybe add.. so you can check for errors before calling get_a()
A* B::get_A_ptr() const
{
return dynamic_cast<A*>(a);
}
dynamic_cast works fine, but can slow down your app if you need to make frequent reads of a->mem.
Store a in an A*, which is probably what you meant to do from the start...
class B
{
// ...
private:
A* a; // now a->A::mem is visible.
};
Since you explicitly call new A in B's constructor, I think option 2 is better for your case.
I am very new to c++ so I am trying to get a feeling of how to do things the right way in c++. I am having a class that uses one of two members. which one gets determined at instantiation. It looks something like
main() {
shared_pointer<A> a = make_shared<A>();
if ( checkSomething ) {
a->setB(make_shared<B>());
} else {
a->setC(make_shared<C>());
}
a->doStuff();
class A {
public:
doStuff() {
/*here I want to do something like call
m_b->doStuff() if this pointer is set and m_c->doStuff() if
that pointer is set.*/
}
setB( B* p ) { m_b = p; }
setC( C* p ) { m_c = p; }
B* m_b;
C* m_c;
}
}
B and C are some classes with doStuff() member function
There are many members like doStuff. Ideally I would avoid checking for nullptr in each of them. What is the best/most efficient/fastest way to create a switch between those two members?
Is there a way to use a static pointer so that I have a member
static **int m_switch;
and do something like
m_switch = condition ? &m_b : &m_c;
and call
*m_switch->doStuff();
Does the compiler here also replace the extra pointer hop because it is a static?
Is there any other smart way to do those switches?
Normally, class A would be an interface class, which both B and C would inherit and implement. But it sounds like you cannot do this for whatever reason.
Since you want to emulate this, you can start by making the interface:
class A_interface
{
public:
virtual void doStuff() = 0;
virtual void doThings() = 0;
virtual void doBeDoBeDo() = 0;
};
And then you make a template wrapper:
template< class T >
class A : public A_interface
{
public:
void doStuff() override { target.doStuff(); }
void doThings() override { target.doThings(); }
void doBeDoBeDo() override { target.doBeDoBeDo(); }
private:
T target;
};
This essentially does half of what your own example class A was trying to do, but now you can use a common interface. All you need to do is construct the correct templated version you want:
std::shared_ptr<A_interface> a;
if( checkSomething ) {
a = std::make_shared<A<B>>();
} else {
a = std::make_shared<A<C>>();
}
a->doStuff();
You need to have both members implement a common interface to use them similarly. But in order to do that, you need to define the interface and relay the calls to the B and C classes.
// existing classes
class B
{
public:
void doStuff() { std::cout << "B"; }
};
class C
{
public:
void doStuff() { std::cout << "C"; }
};
// define your interface
class I
{
public:
virtual void doStuff() = 0;
};
// new classes
class D : public B, public I
{
public:
void doStuff() override { B::doStuff(); }
};
class E : public C, public I
{
public:
void doStuff() override { C::doStuff(); }
};
// your A class
class A
{
public:
D* b = nullptr; // now type D
E* c = nullptr; // now type E
// your toggle
I* getActive()
{
if (b)
return b;
else
return c;
}
// simple doStuff() function
void doStuff()
{
getActive()->doStuff();
}
};
int main()
{
A a;
if (true)
a.b = new D; // need to initialize as D
else
a.c = new E; // need to initialize as E
a.doStuff(); // prints B
}
But typing this up made me realize that defining D and E could get really tiresome and against what you're trying to save. However, you can define a template to create them like #paddy has done.
There's no one-size-fits-all solution for your problem. What to use depends on your particular problem. A few possible answers:
Interfaces
Strategy Pattern
Pointers (to hold a function or class which implements doStuff)
An interface is like a contract. Any class which inherits from the interface must implement its members. For instance,
class IDoesStuff
{
public:
virtual ~IDoesStuff() {};
virtual void DoStuff() = 0;
};
Can now be used by other classes:
class Foo : public IDoesStuff
{
public:
virtual void DoStuff()
{
// ....
}
};
class Bar : public IDoesStuff
{
public:
virtual void DoStuff()
{
// ....
}
};
And now, in general, one may do:
Foo foo;
IDoesStuff *stuffDoer= &foo;
stuffDoer->doStuff();
This can be used in your particular use case as follows:
class A
{
IDoesStuff *stuffDoer; // Initialize this at some point.
public:
void doStuff() { stuffDoer->doStuff(); }
};
First you must change your memebr variables m_b and m_c to std::shared_ptr.
Add a member variable of type std::function(void()) to hold the target function you want to call. In your sample it is do_stuf.
In your setter functions you can bind target function to your std::function and in do_stuf just call std::function.
(You need a C++11 compiler)
class B
{
public:
void doStuff()
{
}
};
class C
{
public:
void doStuff()
{
}
};
class A
{
public:
void doStuff()
{
m_target_function();
}
void setB(std::shared_ptr<B> p)
{
m_b = p;
m_target_function = std::bind(&B::doStuff, m_b.get());
}
void setC(std::shared_ptr<C> p)
{
m_c = p;
m_target_function = std::bind(&C::doStuff, m_c.get());
}
std::shared_ptr<B> m_b;
std::shared_ptr<C> m_c;
std::function<void()> m_target_function;
};
int _tmain(int argc, _TCHAR* argv[])
{
std::shared_ptr<A> a = std::make_shared<A>();
bool use_B = false;
if (use_B)
{
a->setB(std::make_shared<B>());
}
else
{
a->setC(std::make_shared<C>());
}
a->doStuff();
}
I have a template class which parametrized by another class with deep hierarchy. I want to pass to a function base template class parametrized by another base class. Here is the example:
// Base template class test
#include <stdio.h>
// Base classes
template<class T>
class Method {
public:
Method<T> (T * t) {
this->t = t;
}
virtual int solve() = 0;
protected:
T * t;
};
class Abstract {
public:
virtual int get() = 0;
virtual void set(int a) = 0;
};
// Concrete classes, there might be a few of them
template<class T>
class MethodImpl : public Method<T> {
public:
MethodImpl<T> (T * t) : Method<T>(t) {}
int solve() {
return this->t->get() + 1;
}
};
class Concrete : public Abstract {
public:
int get() {
return this->a;
}
void set(int a) {
this->a = a;
}
protected:
int a;
};
// Uses methods of Base classes only
class User {
public:
int do_stuff(Abstract & a, Method<Abstract> & ma) {
a.set(2);
return ma.solve();
}
};
// Example usage
int main () {
Concrete * c = new Concrete();
MethodImpl<Concrete> * mc = new MethodImpl<Concrete>(c);
User * u = new User();
int result = u->do_stuff(*c, *mc);
printf("%i", result);
return 0;
}
I get this error during compilation:
btc.cpp: In function 'int main()':
btc.cpp:62: error: no matching function for call to 'User::do_stuff(Concrete&, MethodImpl<Concrete>&)'
btc.cpp:50: note: candidates are: int User::do_stuff(Abstract&, Method<Abstract>&)
However it works fine if I create local variables with the same logic:
int main () {
Abstract * a = new Concrete();
Method<Abstract> * ma = new MethodImpl<Abstract>(a);
a->set(2);
int result = ma->solve();
printf("%i", result);
return 0;
}
It is because your do_stuff function is not templated, and there's no simple cast from MethodImpl<U> to MethodImpl<T>.
Something more along the lines of
template<class T>
int do_stuff(T& t, Method<T> & mt) {
...
}
might help.
The types MethodImpl<Concrete> and MethodImpl<Abstract> are different and not related by inheritance. The same can be said of MethodImpl<Abstract> and MethodImpl<Concrete>.
The method user::do_stuff expects a Method<Abstract> &, so it could accept a MethodImpl<Abstract>& (or any other derived type of Method<Abstract>, but not a MethodImpl<Concrete>&.