Is there a way to access superclass methods from a subclass?
I made Apple class as a subclass of Fruit class, but I can not access to setName function in Fruit class from an object of Apple class.
Could you give me any advice?
#include <iostream>
#include <string>
using namespace std;
class Fruit {
public:
Fruit(string str)
{
cout << "Fruit class" << endl;
name = str;
cout << name << endl;
}
void setName(string str) {
name = str;
}
private:
string name;
};
class Apple:Fruit {
public:
Apple() :Fruit("apple"){
cout << "Apple class" << endl;
}
void setName(string str) {
name = str;
}
};
int main()
{
Apple apple;
apple.setName("Orange"); //I can not access to setName function from apple
return 0;
}
Use public inheritance like this:
class Apple : public Fruit
The default visibility for class is private if it's not specified. That is why you're not able to access the public members of the base class because they're now private due to their private visibility.
Contrary to a class, the default visibility for a struct is public i.e.:
struct Base {};
struct Derived : Base {}; // public inheritance
In your code, the overridden setName() method in the derived class is redundant as it cannot manipulate the private data member name directly. You'll have to use the base class method to set the name in your overridden method. As of now, you're not doing anything else in that method so you don't need it.
Here's your working code (live):
#include <iostream>
#include <string>
using namespace std;
class Fruit {
public:
Fruit(string str)
{
cout << "Fruit class" << endl;
name = str;
cout << name << endl;
}
void setName(string str) {
name = str;
}
private:
string name;
};
class Apple : public Fruit { // public inheritance
public:
Apple() :Fruit("apple"){
cout << "Apple class" << endl;
}
// void setName(string str) { // Redundant!
// name = str; // `name` is not accessible here!
// }
};
int main()
{
Apple apple;
apple.setName("Orange"); // Accessible here
return 0;
}
For more relevant information, refer to this:
Difference between private, public, and protected inheritance
Your Apple class is using private inheritance (the default when the type of inheritance is not specified), so all of Fruit's public methods are private in Apple and thus are not accessible for main() to call. You need to use public inheritance instead to fix that.
Also, there is no need to re-implement setName() in Apple. The inherited setName() from Fruit will suffice, once it is inherited as a public method in Apple.
class Apple : public Fruit {
public:
Apple() : Fruit("apple"){
cout << "Apple class" << endl;
}
};
Use public inheritance
class Apple:public Fruit
in class Default is Private
class Apple:Fruit
is same as
class Apple:private Fruit
You made private here, So you can not access member of Fruit by object of Apple even if it is public.
class Apple:public Fruit
{
public:
Apple() :Fruit("apple")
{
cout << "Apple class" << endl;
}
};
Or if you want it is to private use like this
class Apple:Fruit
{
public:
Apple() :Fruit("apple")
{
cout << "Apple class" << endl;
}
void setName(string str)
{
Fruit::setName(str);
}
};
First, change class Apple to
class Apple: public Fruit
then, use this method
apple.Fruit::setname()
Related
I am trying to use a public C++ library and extend it for my purposes. To extend it, I need to change a single virtual method within a single class. The method I am trying to override is part of an inherited class. I posted essentially what I need to do in the code below. I don't really want to rename the function because it is used in a multitude of other places and I don't want to change the source code of the library because it works for some cases, but not mine specifically.
#include <iostream>
class Base {
public:
virtual void getName() = 0;
};
class Dynamic : public Base {
public:
virtual void getName() {
std::cout << "Wrong answer\n";
}
};
//Error in redefinition of class method
void Dynamic::getName() {
std::cout << "Right answer\n";
}
int main()
{
Dynamic mydynam;
mydynam.getName();
}
Here is the code example based on the comments above.
The MyDynamic class is derived from the Dynamic class with the function re-implementation.
It will give you the right answer.
#include <iostream>
class Base {
public:
virtual void getName() = 0;
};
class Dynamic : public Base {
public:
virtual void getName() {
std::cout << "Wrong answer\n";
}
};
////////////////////////
class MyDynamic : public Dynamic {
public:
void getName() {
std::cout << "Right answer\n";
}
};
int main()
{
MyDynamic mydynam;
mydynam.getName();
}
I don't know how access to private variable Multiple Inheritance.
In this code I create person class
class person {
char name[20]; char lname[20];
public:
person() {}
person(char*n, char*ln);
virtual void print(ostream&o);
};
person::person(char*n, char*ln)
{
strcpy_s(name, 20, n);
strcpy_s(lname, 20, ln);
}
void person::print(ostream&o)
{
o << "name: " << name << " " << "last name: " << lname << endl;
}
ostream& operator<<(ostream&o, person&p)
{
p.print(o);
return o;
}
by Inheritance I create student and teacher class
class student : public virtual person
{friend class ststudent;
long str;
public:
student(char*n, char*ln, long s);
void print(ostream&o);
};
student::student(char*n, char*ln, long s) :person(n, ln), str(s) {}
void student::print(ostream&o)
{
person::print(o);
o << "st_num : " << str << endl;
}
class teacher : public virtual person
{
long salary;
public:
teacher(char*n, char*ln, long s);
virtual void print(ostream&o);
};
teacher::teacher(char*n, char*ln, long sal) :person(n, ln), salary(sal) {}
void teacher::print(ostream&o)
{
person::print(o);
o << "salary : " << salary << endl;
}
and in last class I use from Multiple Inheritance to create teacher assistant class but I don't know how to print the str and salary
class stteacher :public teacher, public student
{
public:
stteacher(char*n, char*ln, long st, long sa)
:student(0, 0, st), teacher(0, 0, sa), person(n, ln) {}
virtual void print(ostream&o);
};
void stteacher::print(ostream& o)
{
person::print(o);
o << str << salary;
}
I don't know how to do it. I can create two variables in stteacher class or change str and salary from private to public variable but I think I should do this with Multiple Inheritance.
Help me please.
Private data in a class cannot be accessed by any non-member, non-friend code. Period. Whether you use inheritance (or not) is irrelevant.
Thus, the only way for a different class to access that data is to:
Provide accessor function(s) so that callers can fetch the data. (If public, anyone can call it, but if it's a protected function then only derived classes gain access to it.)
Alternately, make the class(es) that need access a friend of the class. Friendship is something c++ programmers generally discourage, however, so only do so as a true last resort.
Change the access to the data to be public. (Very discouraged, as this defeats encapsulation entirely.)
A pattern for accessing private variables is to make a public function that returns that variable:
class teacher : public virtual person
{
long salary;
public:
teacher(char*n, char*ln, long s);
virtual void print(ostream&o);
long get_salary(void){return salary;}
};
Then the implentation for stteacher::print would be:
void stteacher::print(ostream& o)
{
person::print(o);
o << get_salary();
}
or something like this.
Classes by default are private, which means that anything before specifying access modifiers is private.
Private methods / local variables can only be accessed by the class that defined them and it's friend classes. In your case, to define a friend class you should first tell to student and teacher what stteacher is.
C++ reads your code from top to bottom, so if you want to use a variable/class/macro/whatever, you should declare it above it's use.
In code, this would look something like:
extern class stteacher; //You tell C++ that 'stteacher' is a class
class person {};
class student : public virtual person {
long str;
friend class stteacher; //You make stteacher a friend of student
public:
student(long str) : str(str) {}
};
class teacher : public virtual person {
long salary;
friend class stteacher; //You make stteacher a friend of teacher
public:
teacher(long salary) : salary(salary) {}
};
class stteacher : public student, public teacher {
public:
stteacher(long str, long salary) : student(str), teacher(salary) {}
void print() {
std::cout << "Salary: " << salary << "\nStr: " << str << std::endl;
}
}
int main() {
long str = 10, salary = 100;
stteacher(str, salary).print();
return 0;
}
Salary: 100
Str: 10
Eventhough this works, I suggest it would be best to use a more apropiate access modifier, such as protected.
protected stuff can be accessed by the class which defines it, it's friend classes AND classes which inherits it.
Using protected access modifiers, the above code would look like:
extern class stteacher; //You tell C++ that 'stteacher' is a class
class person {};
class student : public virtual person {
protected: //Can be accessed by it's childs
long str;
public:
student(long str) : str(str) {}
};
class teacher : public virtual person {
protected: //Can be accessed by it's childs
long salary;
public:
teacher(long salary) : salary(salary) {}
};
class stteacher : public student, public teacher {
public:
stteacher(long str, long salary) : student(str), teacher(salary) {}
void print() {
std::cout << "Salary: " << salary << "\nStr: " << str << std::endl;
}
}
int main() {
long str = 10, salary = 100;
stteacher(str, salary).print();
return 0;
}
Salary: 100
Str: 10
I'm running into an error "C2084 - function 'void Pet::display(void)' already has a body". Error occurs on Dog.cpp file. Slightly confused about the issue. Any help would be appreciated.
Pet.h
#ifndef _PET_H_
#define _PET_H_
#include <string>
using namespace std;
enum Type { dog = 0, cat };
class Pet {
private:
string name, breed; // private local variables
Type type;
public:
Pet(string pet_name, string pet_breed, Type pet_type); // constructor
// accessor methods
string getName();
string getBreed();
Type getType();
virtual void display() {};
};
#endif // _PET_H_
Dog.h
#ifndef _DOG_H_
#define _DOG_H_
#include "Pet.h"
#include <string>
using namespace std;
class Dog : public Pet {
public:
Dog(string pet_name, string pet_breed, Type pet_type) : Pet(pet_name, pet_breed, pet_type) {
} // constructor
virtual void display() = 0;
};
#endif
Dog.cpp
#include "Dog.h"
#include "Pet.h"
#include <iostream>
void Pet::display() {
cout << "Name: " << name << endl;
cout << "Breed: " << breed << endl;
cout << "Type: Dog" << endl;
}
It seems that you wanted to define Dog::display and have forgotten to rename Pet to Dog:
void Dog::display() {
cout << "Name: " << name << endl;
cout << "Breed: " << breed << endl;
cout << "Type: Dog" << endl;
}
Also remove " = 0" from:
virtual void display() = 0;
in "Dog.h".
In "Pet.h" file having " = 0" after function prototype is ok, it means that you shouldn't instantiate the Pet class directly (Abstract class).
In Pet.h you already have a body defined for display(), which does nothing.
In Pet.h:
class Pet {
/* other class members */
virtual void display() {}; // Here is your virtual function with an empty body.
};
In Dog.h:
class Dog : public Pet {
/* other class members */
virtual void display() = 0; // This pure virtual function which is inheriting from Pet which is not purely virtual.
};
Swap the two around.
Make Pet's virtual void display() = 0, i.e. a pure virtual function.
Make Pet's virtual void display(), i.e. a virtual function which you are already implementing in Dog.cpp.
Solution:
In Pet.h:
class Pet {
/* other class members */
virtual void display() = 0; // Make this a pure virtual function. It does not have an implementation.
};
In Dog.h:
class Dog : public Pet {
/* other class members */
virtual void display(); // This virtual function is implemented in Dog.cpp.
};
You are declaring the method display pure virtual in the class Dog which is derived from another class Pet. But the Pet class already has a concrete method called display. That' why you get this error.
Declare display as pure virtual in the Pet class and then give a concrete implementation in its child class Dog.
I'm trying to use multiple inheritance. Person is my base class. Student and Angestellter inherit the protected attributes. WissenschaftlicheHilfskraft should also inherit these attributes (from Person, Student, Angestellter), but I can't call the method get_name() in my last derived class. Why?
#include <iostream>
using namespace std;
class Person {
protected:
string name;
public: //.......
string get_name() { name = "bob"; return name; }
};
class Student: public Person {
private: //......
public: //......
};
class Angestellte: public Person {
private: //......
public: //......
};
class WissenschaftlicheHilfskraft : public Student, public Angestellte
{
private: //......
public: //......
};
int main()
{
Person p;
cout << p.get_name() << endl; //WORKS
Student s;
cout << s.get_name() << endl; //WORKS
Angestellte a;
cout << a.get_name() << endl; //WORKS
WissenschaftlicheHilfskraft wh;
cout << wh.get_name() << endl; //DOESN'T WORK
return 0;
}
I want it to look like this:
Also, other than Paul R's answer your inheritance is wrong. You need to use virtual inheritance like as shown here.
class Student: public Person { becomes class Student: public virtual Person { and so on. This ensures that only one object of base is created for the final object.
This is the classic "diamond" problem with multiple inheritance. You can work around this by removing the ambiguity, e.g. change:
cout << wh.get_name() << endl; //DOESN'T WORK
to:
cout << wh.Student::get_name() << endl; //WORKS
However, see #Shiv's answer for a better solution which properly resolves the underlying problem.
Can anybody explain why Driver init() method is unable to print name property overridden in child?
#include <iostream>
#include <string>
class Driver {
public:
std::string name = "Unknown";
void init() {
std::cout << name << std::endl;
}
};
// need public here to inherit init()
class SpecificDriver : public Driver {
public:
std::string name = "Specific";
};
int main() {
Driver d;
SpecificDriver sd;
// this gives Unknown Unknown =/
d.init();
sd.init();
}
This gives:
Unknown
Unknown
And should be:
Unknown
Specific
Live Demo
You are not doing quite what you think you may be. You are declaring a variable "name" in driver and a variable "name" in SpecificDriver. When you call init() defined in base class driver, that driver can only access its own name field with value "unknown".
Instead you should initialize the "name" variable using a constructor.
Like this:
class Driver {
public:
std::string name;
Driver():name("Unknown"){} //default
Driver(std::string value):name(value){}
void init() {
std::cout << name << std::endl;
}
};
// need public here to inherit init()
class SpecificDriver : public Driver {
public:
SpecificDriver():Driver("Specific"){}
};
int main() {
Driver d;
SpecificDriver sd;
d.init();
sd.init();
}
Edit: Live Demo http://coliru.stacked-crooked.com/a/c453758867454348
In C++, virtual inheritance is opt-in and not implicit.
When you have this code
class Driver {
public:
std::string name = "Unknown";
void init() {
std::cout << name << std::endl;
}
};
the symbol name will be resolved statically based on what is in scope at that time.
If you later declare a global variable name it has no effect on the meaning of this code. If you later derive from this class Driver, the init function when it is inherited for that class, won't have a different meaning, as in your example.
This "static" dispatch is the default behavior in C++ because it is the simplest and fastest. Especially, it is important that it works this way if you are doing things with templates and inheritance later, otherwise lots of code would have lots of extra overhead.
Alex Zywicki shows one way that you could achieve what you want. Another way would be to use virtual dispatch to get the string. Something like this:
class Driver {
public:
virtual std::string name() const {
return "Unknown";
}
void init() {
std::cout << name() << std::endl;
}
};
class SpecificDriver : public Driver {
virtual std::string name() const override {
return "Specific";
}
};
It is possible to access the class member of the child class through CRTP.
#include <iostream>
template <typename Derived>
class Driver {
public:
void init() {
std::cout << static_cast<Derived*>(this)->name << std::endl;
std::cout << Derived::value << std::endl;
}
};
class SpecificDriver : public Driver<SpecificDriver> {
public:
std::string name = "Specific";
static constexpr char* value = "Another specific string";
};
int main() {
SpecificDriver g;
g.init();
}
If you need a common base class for storing these in, or combining with normal polymorphic behavior you can make the template class Driver inherit from a common base class.