#include <iostream>
using namespace std;
class ParentClass
{
public:
int id;
ParentClass(int id)
{
this->id = id;
}
void print()
{
cout << id << endl;
}
};
class ChildClass: public ParentClass
{
public:
int id;
ChildClass(int id): ParentClass(1)
{
this->id = id;
}
};
int main()
{
ChildClass c(2);
c.print();
return 0;
}
I run this C++ file and I get '1' as output, I want to know how should I write to get '2' as output ? Or say that how to access a redefined variable from a derived class.
You cannot access ChildClass::id from ParentClass::print. More generally: You cannot access members of a derived class, from a member function of the parent.
You can access ChildClass::id within the member functions of ChildClass.
ChildClass::id isn't a "redefined" variable. It is a separate, unrelated variable that happens to have the same identifier, but in different scope. There is no concept of "redefining" a member variable in a derived class, in C++.
I recommend considering, whether it makes sense for ChildClass to have two different ids.
Your ChildClass is doing some wrong or discutable stuff:
1. it's "shadowing" the int id member of ParentClass
2. it's calling the ParentClass constructor passing 1 (instead of "id")
3. it's using assignements in constructors instead of initializer lists
4. ParentClass::id visibility may be decreased from public to protected or private.
Try the following modified code:
#include <iostream>
class ParentClass
{
public:
int id;
ParentClass(int id) : id(id) {}
void print()
{
std::cout << id << std::endl;
}
};
class ChildClass: public ParentClass
{
public:
ChildClass(int id): ParentClass(id) {}
};
int main()
{
ChildClass c(2);
c.print();
return 0;
}
Related
What I'm trying to do is to change a variable from class A inside class B and make it the same in class C
class A
{
protected:
string name = "A";
};
class B: public A
{
protected:
string A::name="B";
};
class C: public B
{
// here i want "name" to be "B"
};
But the problem is, i'm getting an error in class C "illegal qualified name in member declaration".
You can't do it like this. If the field is being initialized in the base class, it is being initialized only in the base class. In other classes you can only change already initialized field.
One of the ways to do what you want can be passing the value in the constructor. So:
class A
{
public:
A(std::string initName = "A") : name(std::move(initName)) {}
protected:
string name;
};
class B: public A
{
public:
B() : A("B") {}
};
class C: public B
{
// name will be "B" here
};
what you want is to initialize the value of your variable in the constructor
public class B: public A
{
public:
B():name{"B"}{};
}
If the names of the classes are static and you don't mind using polymorphism, you could add a virtual member function returning the name of the class. Simply override the function in the derived classes to return a different name.
Example:
#include <iostream>
#include <memory>
#include <vector>
class A {
public:
virtual ~A() = default;
virtual const std::string& name() const {
static const std::string rv = "A";
return rv;
}
};
class B : public A {
public:
const std::string& name() const override {
static const std::string rv = "B";
return rv;
}
};
class C: public B {
// doesn't override name() - will be named "B"
};
int main() {
std::vector<std::unique_ptr<A>> objs; // Storage of base class pointers.
objs.emplace_back(std::make_unique<A>()); // Add pointers to...
objs.emplace_back(std::make_unique<B>()); // objects of different...
objs.emplace_back(std::make_unique<C>()); // derived classes.
// call the virtual member function through the base class pointer
for(auto& uptr : objs) {
std::cout << uptr->name() << '\n';
}
}
Output
A
B
B
#include <iostream>
#include <vector>
class Entity
{
public:
bool hinders_sight = false;
};
class Pillar : public Entity
{
public:
bool hinders_sight = true;
};
int main()
{
std::vector<Entity*> Entities;
Pillar pillar;
Entities.push_back(&pillar);
std::cout << pillar.hinders_sight << std::endl;
std::cout << Entities[0]->hinders_sight << std::endl;
return 0;
}
pillar.hinders_sight returns true (as it should)
but
Entities[0]->hinders_sight returns false.
How can I reach hinders_sight of pillar from the vector?
What is happening right now is that there are two variables called hinders_sight in your derived class, one from the base class and another of the derived class.
There are two main approaches to solve this problem here (I would not recommend keeping two separate variables for the same thing in your base and derived classes), either you can make the variable a protected/private variable in the base class and then offer functions to get and store the variable as needed, or you can make the get_hinders_sight() function virtual.
class Entity {
public:
Entity(bool hinders_sight_in = false)
: hinders_sight{hinders_sight_in} {}
bool get_hinders_sight() { return this->hinders_sight; }
private:
bool hinders_sight = false;
};
class Pillar : public Entity {
public:
Pillar() : Entity{true} {}
};
Or
class Entity {
public:
virtual bool get_hinders_sight() { return false; }
};
class Pillar : public Entity {
public:
bool get_hinders_sight() override { return true; }
};
Use a virtual bool HindersSight(){return hinders_sight;} as variables are not virtual.
Edit: Oh and make your variables protected or private to promote encapsulation. You could complete get rid of the variable and implement HindersSight() for each class to directly return true or false.
Big edit:
I have a code in which I have to add a constant member in a inherited class by using _elemente (which is a vector). Not to add a member in the inherited classes, just by using _elemente. In every inherited classes (let's say B, C, D and E) I withh have MAX_VAL1, MAX_VAL2 and so on with different values.
I tried:
#include <iostream>
#include <iomanip>
#include <vector>
typedef unsigned int Uint;
typedef vector<Uint> TVint;
typedef vector<Uint>::const_iterator TIterator;
class A
{
protected:
Uint _count;
TVint _elemente;
public:
//
};
class B : public A
{
const int MAX_VAL;
};
But it has a member and I don't have to have a member in the inherited class.
All the code here:
.h: http://pastebin.com/P3TZhWaV
.cpp: http://pastebin.com/ydwy2L5a
The work from the inherited classes is done using that constant members.
if MAX_VAL1 < count
{
throw Exception() {}
}
if (_elemente.size() == 0) // As _elemente is a vector from STL
{
_elemente.push_back(0);
}
for (int i = _elemente.size(); i < count; i++)
{
_elemente.push_back(_elemente[i * (i+1) / 2]);
}
}
I don't think that is correct as I have to use the Vector from STL and I don't really think that is the way the constant member from a inherited class without the actual member declared should be added.
Thanks for your help.
You could use a virtual function, something like this:
class A
{
virtual int max_val() const = 0;
protected:
Uint _count;
TVint _elemente;
public:
//
};
class B : public A
{
int max_val() const { return 42; }
};
if ( max_val() < _count ) ...
Based on other comments it seems like you want a const number that is accessible in the base class which can have a different value depending on the derived class. You could achieve that like this: https://ideone.com/JC7z1P
output:
A: 50
B: 80
#include <iostream>
using namespace std;
class Base
{
private:
const int aNumber;
public:
// CTOR
Base( const int _aNumber ) :
aNumber( _aNumber ) {}
// check value
int getNumber() const
{
return aNumber;
}
};
class A : public Base
{
public:
A() : Base( 50 ) {}
};
class B : public Base
{
public:
B() : Base( 80 ) {}
};
int main() {
A a;
B b;
std::cout << "A: " << a.getNumber() << std::endl;
std::cout << "B: " << b.getNumber() << std::endl;
return 0;
}
When you write like
class B : public A
{
const int MAX_VAL;
};
what value do you expect B's class instance to hold with current approach?
Have you tried to add ctor to B (to initialize MAX_VAL to some exact value), so that whole class definition should be like
class B : public A
{
const int MAX_VAL;
public:
B(int max_val):MAX_VAL(max_val) {}
};
Also, the code above shows a lot of unanswered questions. Some of them:
Do you really need it to be member? mark it as 'static' (static const int MAX_VAL = 5) . That would mean, every B's instance MAX_VAL would be equal
All of type redifinitions don't look meaningful. What if you use intrisic types and auto?
Usually one doesn't compare size() with 0 - just calls empty().
Have you tried to read Stroustrup or Lippman?
If you want to access it statically, you can do it by using templates :
ABase gives polymorphic access to value
A gives static access to value
B and Care examples of usage
.
// This is the polymorphic root class
class ABase
{
public:
ABase(int maxV) : _maxV(maxV) {}
int maxValue() { return _maxV; }
private:
int _maxV;
};
// This class gives static method
template<int V_MaxValue>
class A : public ABase
{
public:
A() : ABase(V_MaxValue) {}
static int maxValue() { return V_MaxValue; }
};
class B : public A<42>
{
};
class C : public A<35>
{
};
// Static access (neex explicit class call) :
// B::maxValue() => 42
// C::maxValue() => 35
//
// Polymorphic call :
// ABase* poly = new B();
// poly->maxValue() => 42
I haven't worked with derived classes and polymorphism in a while, and I can't figure out how to access a derived class data item.
// Quick example
class Base {
string data1; // data1 = "FOO"
};
class ChildA : public Base {
string data2;
};
int main() {
Base **list;
list = new Base*[1];
base[0] = new ChildA(// data2 = "BAR");
std::cout << base[0]->data1; // FOO
std::cout << base[0]->data2; // Error; no member named "data2" in Base
Is it possible to retrieve the derived data from the base class array?
When you're looking at an instance of a derived class through a pointer to the base class, you can only see the members of the base class, because generally, you wouldn't know what subtype instance you are looking at. The point of polymorphism and virtual functions is that in many cases, you can work with subtype instances without knowing their actual type. For instance, if you want to print information about an instance, and you want data2 to be included when you print a ChildA, you would create a virtual toString() function in Base and override it in ChildA to include data2. Then, you can call toString() without knowing the actual type, and if your instance is actually a ChildA, you'll get data2.
class member variable by default is private.
by using base class pointer, you can not get derived class member var at all.
If you would like to do so, you may want to implement virtual getter function, it will help you getting private member function from derived class.
If the base class interface must have knowledge of data potentially held in a derived class, here is one of the few ways that is not horribly dangerous.
#include <iostream>
#include <vector>
#include <utility>
#include <memory>
#include <stdexcept>
using namespace std;
class Base {
public:
Base(std::string d1 = {"FOO"} ) : _data1 { std::move(d1) } {}
virtual ~Base() = default; // because polymorphism without a virtual base class is naughty
const string& data1() const { return _data1; }
virtual bool has_data2() const { return false; }
virtual const string& data2() const {
throw invalid_argument {"I don't have data2"};
};
private:
string _data1; // data1 = "FOO"
};
class ChildA : public Base {
public:
ChildA(std::string d2, std::string d1 = {"FOO"})
: Base { std::move(d1) }
, _data2 { std::move(d2) }
{}
bool has_data2() const override { return true; }
const std::string& data2() const override {
return _data2;
};
private:
string _data2;
};
int main()
{
vector<unique_ptr<Base>> bases;
bases.push_back(unique_ptr<Base>(new ChildA("bob")));
bases.push_back(unique_ptr<Base>(new Base("not foo")));
for(const auto& p : bases) {
cout << p->data1() << ", " << (p->has_data2() ? p->data2() : "no data 2") << endl;
}
return 0;
}
My question might not be too correct... What I mean is:
class MyClass
{
public:
MyClass()
{
}
virtual void Event()
{
}
};
class FirstClass : public MyClass
{
string a; // I'm not even sure where to declare this...
public:
FirstClass()
{
}
virtual void Event()
{
a = "Hello"; // This is the variable that I wish to pass to the other class.
}
};
class SecondClass : public MyClass
{
public:
SecondClass()
{
}
virtual void Event()
{
if (a == "Hello")
cout << "This is what I wanted.";
}
};
I hope that this makes at least a little sense...
Edit: _This changed to a.
What you need to do is make SecondClass inherit from FirstClass and declare _This as protected.
class FirstClass : public MyClass
{
protected:
string _This;
public:
and
class SecondClass : public FirstClass
What you got doesn't make sense because classes can only see members and functions from their parents (MyClass in your case). Just because two class inherit from the same parent does not mean they have any relation or know anything about each other.
Also, protected means that all classes that inherit from this class will be able to see its members, but nobody else.
I guess that you need something like this (for a sake of simplicity, I've omitted all the unnecessary code):
class Base{
public:
~Base(){}
protected:
static int m_shared;
};
int Base::m_shared = -1;
class A : public Base{
public:
void Event(){
m_shared = 0;
}
};
class B : public Base{
public:
void Event(){
if (m_shared == 0) {
m_shared = 1;
}
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
B b;
a.Event();
b.Event();
return 0;
}
To explain above, I'll explain the static data members:
Non-static members are unique per class instance and you can't share them between class instances. On the other side, static members are shared by all instances of the class.
p.s. I suggest that you read this book (especially Observer pattern). Also note that above code is not thread-safe.