In the following, I expected class Child's protected field member _AorB to be of type B, and not A, but reality shows otherwise.
What am I mis-understanding, and how can I adjust the code for the desired behavior?
class A{
public:
void doit(){
std::cout<<" this is A!"<<std::endl;
}
};
class B{
public:
void doit(){
std::cout<<" this is B!"<<std::endl;
}
};
class Parent{
public:
void doit(){
_AorB.doit();
}
protected:
A _AorB;
};
class Child: public virtual Parent{
protected:
B _AorB;
};
int main()
{
cout<<"Hello World";
auto c = Child();
c.doit(); // I expected this to print "This is B" because c is Child(), and Child class's _AorB is of type B.
return 0;
}
You can make such changes:
template <typename AorB>
class Parent{
public:
void doit(){
_AorB.doit();
}
protected:
AorB _AorB;
};
class Child: public virtual Parent<B> {
}
Also take a look at What are the rules about using an underscore in a C++ identifier?
Reserved in any scope, including for use as implementation macros:
identifiers beginning with an underscore followed immediately by an uppercase letter
273K's answer is excellent.
Depending on what kind of problem you are trying to solve and how the data is held in the hierarchy, you could use a std::variant<A, B> to allow "flippy" behavior based on the type, and access that member variable through a virtual getter member function.
#include <iostream>
#include <variant>
class A {
public:
void doit() {
std::cout << " this is A!\n";
}
};
class B {
public:
void doit() {
std::cout << " this is B!\n";
}
};
class Parent {
public:
virtual ~Parent() = default;
void doit() {
auto ab = get_AorB();
std::visit([](auto arg) { arg.doit(); }, ab);
}
virtual auto get_AorB() -> std::variant<A, B> {
return _a;
}
protected:
A _a;
};
class Child : public virtual Parent {
protected:
B _b;
auto get_AorB() -> std::variant<A, B> override {
return _b;
}
};
int main() {
std::cout << "Hello World";
auto c = Child();
c.doit(); // "this is B!"
}
Related
This question already has answers here:
How to store object of different class types into one container in modern c++?
(2 answers)
Closed 3 years ago.
I have multiple classes with same function as below
class A
{
void display()
{
// display something
}
};
class B
{
void display()
{
// display something two
}
};
I want to store difference class at a list or a vector and loop to call the same function with same name
int main()
{
A * a;
B * b;
//list or vector to store object
std::vector < Something that can store different class > listofclass;
listofclass.emplace_back(a);
listofclass.emplace_back(b);
for (int i = 0; i < listofclass.size(); i++)
{
listofclass[i].display();
}
}
Is that possible to do like this?
Because there is separate classes, having different purpose, and now i try to group them together
Or there is other alternative way to achieve something like this
If you control the definition of A and B, you can write a common base class, and have them inherit it.
class can_display {
public:
virtual void display() = 0;
virtual ~can_display() = default;
};
class A : public can_display
{
void display() override
{
// display something
}
};
class B : public can_display
{
void display() override
{
// display something two
}
};
int main()
{
A a;
B b;
std::vector<can_display *> displayables;
displayables.push_back(&a);
displayables.push_back(&b);
for (can_display * displayable : displayables)
{
displayable->display();
}
}
As an alternative to changing the definition of A and B to inherit from a common base, you can have a wrapper that inherits.
template <typename T>
class can_display_impl {
T * wrapped;
public:
can_display_impl(T * wrapped) : wrapped(wrapped) {}
void display() override { wrapped->display(); }
}
template <typename T>
std::unique_ptr<can_display> make_can_display(T & wrapped) {
return std::make_unique<can_display_impl<T>>(&wrapped);
}
int main()
{
A a;
B b;
std::vector<std::unique_ptr<can_display>> displayables;
displayables.emplace_back(make_can_display(a));
displayables.emplace_back(make_can_display(b));
for (auto & displayable : displayables)
{
displayable->display();
}
}
You have two solutions for this problem:
Use inheritance and just make a abstract class that will be a interface for your classes. In class A and class B just inherit from that interface and in std::vector hold pointer to base class.
#include <vector>
#include <iostream>
#include <memory>
class Interface_display {
public:
virtual void display() = 0;
virtual ~Interface_display(){};
};
class A : public Interface_display
{
public:
void display() override
{
std::cout << "Display from A\n";
}
~A() override = default;
};
class B : public Interface_display
{
public:
void display() override
{
std::cout << "Display from B\n";
}
~B() override = default;
};
int main(void)
{
std::vector<std::unique_ptr<Interface_display>> v;
v.emplace_back(std::make_unique<A>());
v.emplace_back(std::make_unique<B>());
for (const auto &element: v) {
element->display();
}
}
And if you are using c++17, you could use std::variant and wrap objects of your class to std::variant:
#include <vector>
#include <iostream>
#include <variant>
class A
{
public:
void display()
{
std::cout << "Display from A\n";
}
};
class B
{
public:
void display()
{
std::cout << "Display from B\n";
}
};
int main(void)
{
using variant_t = std::variant<A, B>;
std::vector<variant_t> v;
v.emplace_back(A());
v.emplace_back(B());
for (auto &element: v) {
std::visit([](auto &x) { x.display(); }, element);
}
}
https://wandbox.org/permlink/8VBmziWzafbPZk99
A way to solve this problem is by using polymorphism. You make a superclass, which contains a pure virtual version of this function and let both A and B inherit from this class. By doing this, you can dynamic_cast any pointer of type A or B to a superclass type, on which you have defined the display function.
This will get you something like this
class C {
public:
virtual void display() = 0;
virtual ~C() = default;
};
class A : public C {
public:
void display() override {
std::cout << "A" << std::endl;
};
~A() override = default;
};
class B : public C {
public:
void display(){
std::cout << "B" << std::endl;
};
~B() override = default;
};
So you can do:
C* c = new A();
// You can put the types of C* in the same list, and iterate over this list and do on each element
c->display();
delete c;
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.
How to do multiple inheritance just for function?
must share data of the base class
no virtual function (assume that vtable is expensive)
avoid virtual inheritance
implementation must be able to reside in .cpp
c++14 is allowed
Here are similar questions :-
Multiple inheritance in diamond shape with functions only - use virtual inheritance. Virtual inheritance is generally bad and expensive.
multiple inheritance without virtual inheritance - focuses on syntax and compiling rather than programming technique.
Multilevel inheritance in c++ (CRTP) , CRTP and multilevel inheritance , Eliminate redundancy with CRTP and multiple inheritance (C++03) and Using CRTP with virtual inheritance - implementation must be in header
Here is a sample code (coliru demo) :-
class O{
protected: int database=0;
};
class A : public O{
public: void print(){
std::cout<<database<<std::endl;
}
};
class B : public O{
public: void set(int s){
database=s+1;
}
};
class AB : public O{
public: void print(){//duplicate
std::cout<<database<<std::endl;
}
public: void set(int s){//duplicate
database=s+1;
}
};
//AB ab; ab.set(1); ab.print(); // would print 2
Here is my attempt (wandbox demo). I abuse CRTP :( :-
class O{
public: int database=0;
};
template<class T>class OA{
public: void print(){
std::cout<<static_cast<T*>(this)->database<<std::endl;
}
};
template<class T>class OB{
public: void set(int s){
static_cast<T*>(this)->database=s+1;
}
};
class A :public O,public OA<A>{};
class B :public O,public OB<B>{};
class AB :public O,public OA<AB>,public OB<AB>{};
It works, but it looks inelegant.
Furthermore, implementation must be in header (because OA and OB are template classes).
Are there better approaches? Or is this the way to go?
Sorry if it is too newbie question or already asked. I am a C++ beginner.
Edit
Give extended example of using please.
In ECS, it would be useful in some cases :-
class O{
protected: EntityHandle e;
};
class ViewAsPhysic : public O{ //A
public: void setTransform(Transformation t){
Ptr<PhysicTransformComponent> g=e;
g->transform=t;
}
};
class ViewAsLight : public O{ //B
public: void setBrightness(int t){
Ptr<LightComponent> g=e;
g->clan=t;
}
};
class ViewAsLightBlock : public O{ //AB
//both functions
};
The problem here is that the database field is member of class O. So without virtual inheritance, A and B will have each their own copy of database. So you must find a way to force A and B to share same value. You could for example use a reference field initialized in a protected constructor:
#include <iostream>
class O{
int _db;
protected: int &database;
O(): database(_db) {};
O(int &db): database(db) {};
};
class A : public O{
public: void print(){
std::cout<<database<<std::endl;
}
A() {} // public default ctor
protected: A(int& db): O(db) {}; // protectect ctor
};
class B : public O{
public: void set(int s){
database=s+1;
}
B() {} // public default ctor
protected: B(int& db): O(db) {}; // protectect ctor
};
class AB : public A, public B {
int _db2;
public: AB(): A(_db2), B(_db2) {}; // initialize both references to same private var
};
int main() {
AB ab;
ab.set(1);
ab.print();
return 0;
}
displays as expected:
2
Above code uses no virtual inheritance, no virtual function and no templates, so method can safely implemented in cpp files. The class AB actually uses methods from its both parents and has still a coherent view on its underlying data. In fact it simulates an explicit virtual inheritance by building the common data in the most derived class and injecting in through protected constructors in its parents.
Something like this?
must share data of the base class - check
no virtual function (assume that vtable is expensive) - check
avoid virtual inheritance - check
implementation must be able to reside in .cpp- check
c++14 is allowed - check. c++11 used.
#include <iostream>
class O {
protected:
int database = 0;
};
/*
* the concept of implementing print for a base class
*/
template<class...Bases>
struct implements_print : Bases... {
void print() const {
std::cout << this->database << std::endl;
}
};
/*
* The concept of implementing set for a base class
*/
template<class...Bases>
struct implements_set : Bases... {
void set() {
++this->database;
}
};
struct B : implements_set<O> {
};
struct A : implements_print<O> {
};
struct AB : implements_set<implements_print<O>> {
};
int main() {
A a;
a.print();
B b;
b.set();
AB ab;
ab.set();
ab.print();
}
Another way, using composition and an access class to provide access to the protected member. This example shows how to defer the work on database to another compilation unit:
#include <iostream>
/*
* this stuff in cpp
*/
namespace implementation
{
void print(const int& database) {
std::cout << database << std::endl;
}
void set(int& database) {
++database;
}
}
/*
* this stuff in header
*/
struct OAccess;
class O {
private:
int database = 0;
friend OAccess;
};
struct OAccess {
template<class Host>
constexpr decltype(auto) database(Host &host) const { return (host.database); } // note: () makes reference
template<class Host>
constexpr decltype(auto) database(Host const &host) const { return (host.database); } // note: () makes reference
};
/*
* the concept of implementing print for a derived class
*/
template<class Host>
struct implements_print {
void print() const {
OAccess access;
implementation::print(access.database(self()));
}
private:
decltype(auto) self() const { return static_cast<Host const &>(*this); }
};
/*
* The concept of implementing set for a derived class
*/
template<class Host>
struct implements_set {
void set() {
OAccess access;
implementation::set(access.database(self()));
}
private:
decltype(auto) self() { return static_cast<Host &>(*this); }
};
template<template<class> class...Impls>
struct OImpl : Impls<OImpl<Impls...>> ..., O {
};
using B = OImpl<implements_set>;
using A = OImpl<implements_print>;
using AB = OImpl<implements_print, implements_set>;
int main() {
A a;
a.print();
B b;
b.set();
AB ab;
ab.set();
ab.print();
}
We start with defining the concepts of things that can print and things that can be set:
namespace util {
template<class Base, class Derived, class R=void>
using if_base = std::enable_if_t< std::is_base_of< std::decay_t<Base>, std::decay_t<Derived>>::value, R >;
struct stub {};
}
namespace concepts {
template<class Token>
void do_print(Token, util::stub const&)=delete;
template<class Token>
void do_set(Token, util::stub&, int)=delete;
struct has_print {
struct token { friend struct has_print; private: token(int){} };
template<class T>
friend util::if_base<has_print, T> print(T const& t) {
do_print(get_token(), t);
}
private: static token get_token() { return 0; }
};
struct has_set {
struct token { friend struct has_set; private: token(int){} };
template<class T>
friend util::if_base<has_set, T> set(T& t, int x) {
do_set(get_token(),t, x);
}
private: static token get_token() { return 0; }
};
}
We then declare O and the operations you can support on it:
namespace DB {
class O;
void do_print(::concepts::has_print::token, O const& o);
void do_set(::concepts::has_set::token, O& o, int);
class O{
protected: int database=0;
friend void do_print(::concepts::has_print::token, O const&);
friend void do_set(::concepts::has_set::token, O&, int);
};
class A : public O, public concepts::has_print {
};
class B : public O, public concepts::has_set {
};
class AB : public O, public concepts::has_print, concepts::has_set {
};
}
void DB::do_print(::concepts::has_print::token, O const& o ) { std::cout << o.database << std::endl; }
void DB::do_set(::concepts::has_set::token, O& o, int x) { o.database = x+1; }
The hard part of this is the access control.
I ensure it isn't possible to call do_set except through has_set::set.
That is what all those tokens are about. You can strip them out and their overhead if you are willing to just say "don't call the do_ functions" (and maybe give them another name, like private_impl_set).
Live example.
To start discussion.
class O
{
// no virtual destructor. So cant use polymorphic deletion
// like :
// O *o = new AB;
// delete o;
protected: int database=0;
};
class A : virtual public O{
public: void print(){
std::cout<<database<<std::endl;
}
};
class B : virtual public O{
public: void set(int s){
database=s+1;
}
};
class AB : protected A, protected B{}; // no vtable
void foo() {
AB ab;
ab.print(); // won't perform virtual call.
}
I want a class that can only be instantiated as a member of another class.
Id est:
class A
{
public:
A() :
member_()
{};
void letBSayHi() { member_.sayHi(); }
private:
B member_;
};
class B
{
public:
void sayHi() { printf("hola!"); }
};
thus:
A alpha; // valid
alpha.letBSayHi(); // # hola!
B beta; // invalid
beta.sayHi(); // impossible
The singleton pattern obviously wouldn't work, as I want one instance of class B for every instance of class A. But any instantiation of class B other than as a class A-member should be prohibited.
Make B a private nested class of A:
class A {
public:
void letBSayHi() { member_.sayHi(); }
private:
class B {
public:
void sayHi() { std::cout << "hola!"; }
};
B member_;
};
Addendum re: comment: The implementation can be separated from the declaration like this:
Header:
class A {
public:
void letBSayHi();
private:
class B {
public:
void sayHi();
};
B member_;
};
Source file:
void A::letBSayHi() { member_.sayHi(); }
void A::B::sayHi() { std::cout << "hola!\n"; }
// ^^^^-- interesting part here
Well, if you want to include, why not?
class A {
#include "B.hpp"
...
};
This code can help to understand, what I want:
class Base
{
public:
void foo()
{
print("Base\n");
Derived::foo(); // smth like that.
}
};
class Derived:public Base
{
public:
void foo()
{
print("Derived\n");
}
}
int main()
{
Derived bar;
bar.foo();
return 0;
}
Any ideas ?
P.S. very bad idea is pass to foo pointer of derived.
You would need the base class to hold some short of a handle of it's derived class like the example below:
template<typename T>
class Base {
T *handle;
protected:
Base(T *_handle) : handle(_handle) {}
public:
void foo() {
std::cout << "Base" << std::endl;
handle->foo();
}
};
class Derived : public Base<Derived> {
public:
Derived() : Base(this) { }
void foo() { std::cout << "Derived" << std::endl; }
};
LIVE DEMO
Adapted from here:
class Derived:public Base
{
public:
void foo()
{
Base::foo();
print("Derived\n");
}
}
int main()
{
Derived bar;
bar.foo();
}
seems to be what you want.
You can declare an abstract method in Base which sub-classes have to override, but you call it although it is abstract. This called Template Method:
class Base
{
public:
void foo() {
print("Base\n");
_foo();
}
private:
virtual void _foo() = 0;
};
class Derived: public Base
{
virtual void _foo() {
print("Derived\n");
};
};
Another alternative would be to make Base a template and pass the Derived type:
template<class D>
class Base
{
public:
void foo() {
print("Base\n");
D::foo();
}
};
class Derived: public Base<Derived>
{
public:
void foo() {
print("Derived\n");
};
};
I would usually go with the first approach as it is easier to grasp and also works with more than one level of inheritance.
Something like
class Derived : public Base
{
public:
void foo()
{
Base::foo();
printf("Derived\n");
}
};
then
int main()
{
Derived bar;
bar.foo();
return 0;
}
OR
int main()
{
Derived bar;
bar.Base::foo();
bar.Derived::foo();
return 0;
}
You are describing static polymorphism, which is solved by CRTP:
template <typename DERIVED>
class Base
{
public:
DERIVED & derived() { return *static_cast<DERIVED *>(this); }
void foo()
{
print("Base\n");
derived().foo();
}
};
class Derived:public Base<Derived>
{
public:
void foo()
{
print("Derived\n");
}
};
You need a virtual function.
#include "windows.h"
#include <iostream>
class Base
{
public:
virtual void foo() const
{
std::cout << "Base\n";
}
};
class Derived : public Base
{
public:
void foo() const
{
Base::foo();
std::cout << "Derived\n";
}
};
void main()
{
Derived d; // call Base::foo on this object
d.foo();
system("pause");
}