C++ class inheritance and member functions - c++

All,
I am having difficulty understanding why I am getting the following error. I promise this is not a homework problem, but I am new to C++! Here is my code:
#include <iostream>
#include <string>
#include <vector>
class Base {
protected:
std::string label;
public:
Base(std::string _label) : label(_label) { }
std::string get_label() { return label; }
};
class Derived : private Base {
private:
std::string fancylabel;
public:
Derived(std::string _label, std::string _fancylabel)
: Base{_label}, fancylabel{_fancylabel} { }
std::string get_fancylabel() { return fancylabel; }
};
class VecDerived {
private:
std::vector<Derived> vec_derived;
public:
VecDerived(int n)
{
vec_derived = {};
for (int i = 0; i < n; ++i) {
Derived newDerived(std::to_string(i), std::to_string(2*i));
vec_derived.push_back(newDerived);
}
}
std::string get_label(int n) { return vec_derived.at(n).get_label(); }
std::string get_fancylabel(int n) { return vec_derived.at(n).get_fancylabel(); }
};
int main (void)
{
VecDerived obj(5);
std::cout << obj.get_label(2) << " " << obj.get_fancylabel(2) << "\n";
return 0;
}
The compiler error I get is as follows:
test1.cpp: In member function ‘std::__cxx11::string VecDerived::get_label(int)’:
test1.cpp:33:70: error: ‘std::__cxx11::string Base::get_label()’ is inaccessible within this context
std::string get_label(int n) { return vec_derived.at(n).get_label(); }
^
test1.cpp:9:15: note: declared here
std::string get_label() { return label; }
^~~~~~~~~
test1.cpp:33:70: error: ‘Base’ is not an accessible base of ‘__gnu_cxx::__alloc_traits<std::allocator<Derived> >::value_type {aka Derived}’
std::string get_label(int n) { return vec_derived.at(n).get_label(); }
I don't understand why the member function get_label() wasn't inherited from the Base class to the Derived class, such that I'm not able to access it via the VecDerived class. Is there a way that this can be resolved? Thanks in advance for your help!

Visual Studio emits an error message that gives you more hints:
error C2247: 'Base::get_label' not accessible because 'Derived' uses 'private' to inherit from 'Base'
So if you want to access Base::get_label through a Derived object, then you either need to make the base class public:
class Derived : public Base
or make get_label public:
class Derived : private Base {
public:
using Base::get_label;

Related

Retrieving a specific class type element from base class vector in C++

So I have a base class and a derived class:
class BaseClass {
public:
virtual void print() { std::cout << "hi" << std::endl; }
BaseClass() = default;
};
class DerivedClass : public BaseClass {
public:
void print() { std::cout << "bye" << std::endl; }
DerivedClass() = default;
};
I also have a std::vector<BaseClass*> list.
I want to have a function that retrieves the first instance of a chosen class, similar to Unity3D engine's GetComponent function. This is how I tried to implement it:
template <class T>
T* getInstance() {
for(int i = 0; i < (int)list.size(); ++i) {
if(typeid(list[i]) == typeid(T))
return list[i];
}
return nullptr;
}
Can someone please explain to my what I am doing wrong?
Edit: I forgot to mention if I had any errors:
Error C2440 'return': cannot convert from '_Ty' to 'T *' at line return list[i];.
Doesn't seem to have to do with the fact that I don't have any T parameter.
Edit 2:
Added a T parameter as a 'temporary' workaround
Code calling getInstance:
int main() {
getInstance<Derived>(Derived())->print();
return 0;
}

How to create an object globally and access an public member function in the global scope with that object?

I am trying to create an object globally and trying to access the public member function with the help of a constructor. But it is showing error, Can anyone help me please??
Here I created a class named base and trying to access the public member function of the class in the global scope by creating a constructor.
#include <iostream>
using namespace std;
class base
{
void privatef()
{
cout<<"This is function from private scope\n";
}
public:
void publicf()
{
cout<<"This is function from public scope\n";
}
protected:
void protectedf()
{
cout<<"This is function from protected scope\n";
}
};
base()
{
publicf();
//privatef();
//protectedf();
}
base d;
class derived :public base
{
public:
derived()
{
//privatef();
publicf();
protectedf();
}
};
int main()
{
derived d1 ;
return 0;
}
ERROR:
error: expected unqualified-id before ')' token
base()
^
That's the correct form
#include "stdafx.h"
#include <iostream>
using namespace std;
class base
{
void privatef()
{
cout << "This is function from private scope\n";
}
public:
//Declare it at least first & then define it outside
base();
void publicf()
{
cout << "This is function from public scope\n";
}
protected:
void protectedf()
{
cout << "This is function from protected scope\n";
}
};
base::base()
{
publicf();
//privatef();
//protectedf();
}
base d;
class derived :public base
{
public:
derived(){
//privatef();
publicf();
protectedf();
}
};
int main()
{
derived d1;
return 0;
}

Alternative to virtual variables

I have two classes, Base and Derived. Derived inherits from Base and additionally includes several functions and variables -- therefore the need to have two separate classes. However, they do share one function, run.
In the example below I have to pass an argument to run in order to execute read - this argument depends on which class the object refers to. Is it possible to write a generic version of read such that the program automatically uses vars_Base or vars_Derived depending on which object calls run?
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
class Base
{
protected:
void read(std::vector<std::string>);
public:
void run(std::vector<std::string> vars) { read(vars); }
std::vector<std::string> vars_Base;
};
void Base::read(std::vector<std::string> int_vars)
{
for (auto int_vars_it : int_vars)
{
std::cout << int_vars_it << "\n";
}
}
class Derived : public Base
{
protected:
public:
std::vector<std::string> vars_Derived;
///Here are other functions only known to Derived, not Base
};
int main()
{
Base b;
b.vars_Base.push_back("aB");
b.vars_Base.push_back("bB");
b.vars_Base.push_back("cB");
b.run(b.vars_Base);
Derived d;
d.vars_Derived.push_back("aD");
d.vars_Derived.push_back("bD");
d.vars_Derived.push_back("cD");
d.run(d.vars_Derived);
return 0;
}
Is that the result you want to get?
class Base
{
protected:
using vars_type = std::vector<std::string>;
private:
vars_type vars_Base;
protected:
virtual vars_type& get_vars() {
return vars_Base;
}
public:
void push_back(const std::string& str) {
get_vars().push_back(str);
}
void run()
{
for (auto int_vars_it : get_vars()) {
std::cout << int_vars_it << " ";
}
}
};
class Derived : public Base
{
private:
vars_type vars_Derived;
protected:
vars_type& get_vars() override {
return vars_Derived;
}
public:
///Here are other functions only known to Derived, not Base
};
int main(int argc, char* argv[])
{
Base b;
b.push_back("aB");
b.push_back("bB");
b.push_back("cB");
b.run(); // prints aB bB cB
std::cout << std::endl;
Derived d;
d.push_back("aD");
d.push_back("bD");
d.push_back("cD");
d.run(); // prints aD bD cD
return 0;
}
If so then the explanation is next: there is no such thing as a "virtual variable", but there are virtual functions. You can use virtual functions as "internal accessors" for your member variables. Although, Derived class contains both vars_Base and vars_Derived, get_vars() lets you override access to appropriate instance of vars.
Hope you'll find it helpful.
You can make use of virtual functions to solve your problem, without the use for generics.
Here is a solution using virtual functions (applied to your sample code) :
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
class Base
{
protected:
void read(std::vector<std::string>);
public:
virtual void run() { read(vars_Base); }
std::vector<std::string> vars_Base;
};
void Base::read(std::vector<std::string> int_vars)
{
for (auto int_vars_it : int_vars)
{
std::cout << int_vars_it << "\n";
}
}
class Derived : public Base
{
protected:
public:
void run() override { read(vars_Derived); }
std::vector<std::string> vars_Derived;
///Here are other functions only known to Derived, not Base
};
int main()
{
Base b;
b.vars_Base.push_back("aB");
b.vars_Base.push_back("bB");
b.vars_Base.push_back("cB");
b.run();
Derived d;
d.vars_Derived.push_back("aD");
d.vars_Derived.push_back("bD");
d.vars_Derived.push_back("cD");
d.run();
return 0;
}
This solution allows to encapsulate vars_Base and vars_Derived inside the classes.
Hope this helps.

Overriding functions (from two abstract base classes) that differ only by their return value

I want to create a class that implements two interfaces that have functions with a same name that differ only by their return values. How can I do this correctly?
template<class T>
class IBase
{
public:
virtual T Method() = 0;
};
class Derived : public IBase<int>, public IBase<char> {
public:
int _value;
virtual int IBase<int>::Method();
virtual char IBase<char>::Method();
};
int Derived::Method() {
return _value;
}
char Derived::Method() {
return _value;
}
Here are the errors that I get:
error C2555: 'Derived::Method: overriding virtual function return type differs and is not covariant from 'IBase<int>::Method
error C2556: 'int Derived::Method(void)' : overloaded function differs only by return type from 'char Derived::Method(void)'
error C2371: 'Derived::Method: redefinition; different basic types
error C2084: function 'char Derived::Method(void)' already has a body
In C# it's pretty easy to do this without any ambiguities using nearly same syntax (called explicit interface implementation):
class Derived : IBase<int>, IBase<char> {
int _value;
int IBase<int>.Method() {
return _value;
}
char IBase<char>.Method();
return _value;
}
};
Explicitly implementations are private and thus cannot be used directly on variables of class Derived. They are still very usable though as you can cast the Derived to one of the interfaces to use the implementation:
var d = new Derived();
((IBase<int>)d).Method();
This can be rather useful. A class can implement ICanConvertTo many times to enable different conversions.
With virtual in Derived
#include <iostream>
template<typename T>
class IBase
{
public:
virtual T method() = 0;
};
template<typename T>
class WrapBase : public IBase<T>
{
protected:
virtual T do_method(T*) = 0;
public:
virtual T method() {
return do_method((T*)0);
}
};
class Derived : public WrapBase<char>, public WrapBase<int>
{
protected:
virtual char do_method(char*) { return 'A'; };
virtual int do_method(int*) { return 1; };
};
Removing virtual in Derived - Thanks to DyP:
include <iostream>
template<typename T>
class IBase
{
public:
virtual T method() = 0;
};
template<typename D, typename T>
class WrapBase : public IBase<T>
{
public:
virtual T method();
};
class Derived : public WrapBase<Derived, char>, public WrapBase<Derived, int>
{
friend class WrapBase<Derived, char>;
friend class WrapBase<Derived, int>;
protected:
char do_method(char*) { return 'A'; };
int do_method(int*) { return 1; };
};
template<typename D, typename T>
inline T WrapBase<D, T>::method() {
return static_cast<D*>(this)->do_method((T*)0);
}
Test:
int main () {
Derived d;
IBase<char>& c = d;
IBase<int>& i = d;
std::cout << c.method() << " != " << i.method() << std::endl;
}
Comment: Mixing static and dynamic polymorphism might be a bad design.
Function can not differ only by return value, because the compiler has no way to distinguish them. Consider:
long x;
Derived d;
x = d.Method();
both the char and the int variant are possible to convert to an long - which one should it use?
Edit:
If you want to define conversions, the typical case is to define a cast-operator, e.g.
class X
{
float x;
public:
X(float f) : x(f) {}
operator int() { return static_cast<int>(x); }
operator char() { return static_cast<char>(x); }
float getX() { return x; }
};
and then call it as:
X x(65.3);
int y = x;
char z = x;
cout << "x.f=" << x.getF() << " as char:" << z << " as int:" << y << endl;
Returned value type is not part of the function (method) signature.
So your two methods are seen as the same method (so the redefinition error).
So you can't do what you want. your method should have different signature.

Curiously recurring template patterm: double inheritance

I have the following:
class Base
{
protected:
std::string _name;
public:
virtual ~Base(){}
const std::string &name;
Base()
: _name ("(no name)")
, name(_name)
{}
};
template <typename T>
class BaseH : public Base
{
public:
virtual ~BaseH() {}
BaseH() : Base() {}
T& operator~(){ ; return static_cast<T&>(*this);}
};
class One : public BaseH<One>
{
public:
One() : BaseH<One>() { _name = "One"; }
};
class Two
: public One
, public BaseH<Two>
{
public:
Two() : BaseH<Two>() { _name = "Two"; }
};
int main(int argc, char *argv[])
{
std::cout << Two().name << std::endl;
return 0;
}
I want to derive Two from both One and BaseH<Two>, because Two is a specialization of One, and the operator~ in BaseH must always return a reference of the type of the object that's calling it.
Compilation errors are obviously:
In constructor ‘Two::Two()’:
error: reference to ‘_name’ is ambiguous
error: candidates are: std::string Base::_name
error: std::string Base::_name
In function ‘int main(int, char**)’:
error: request for member ‘name’ is ambiguous
error: candidates are: const string& Base::name
error: const string& Base::name
How do I make _name and name accessible in both One and Two, while setting the const references via constructor delegation? What is the cleanest way to do that?
Looks like you've got the diamond problem. Have you tried virtual inheritance?
e.g.:
template <typename T>
class BaseH : virtual public Base
{
// ...
};
class One : virtual public BaseH<One>
{
// ...
};
edit: further reading on the diamond problem here: http://www.cprogramming.com/tutorial/virtual_inheritance.html