Cant use brother methods with virtual inheritance cpp - c++

Because of virtual inheritance, when the write() function from the
transmitter class is called, the method read() from the receiver class
gets called (as you may have noticed, the transmitter class doesn't
have a read() function). In the above hierarchy we can instantiate
only the radio class because transmitter and receiver are abstract due
to virtual inheritance.
http://www.cprogramming.com/tutorial/virtual_inheritance.html
So I tried it and it didnt worked for me.
#pragma once
#include <iostream>
using namespace std;
father class:
class father
{
public:
father(){
};
~father(){};
virtual void printt() = 0;
void sett()
{
printt();
}
void father()
{
cout << "Im your father...";
}
private:
};
Person:
#pragma once
#include <iostream>
using namespace std;
#include "father.h"
class MyClasst: public virtual father
{
public:
MyClasst(){
g = 8;
};
~MyClasst(){};
void print()
{
cout << "a";
}
void c()
{
cout << "bbb";
}
private:
...
};
Student class:
#pragma once
#include <iostream>
#include "father.h"
using namespace std;
class MyClassa: public virtual father
{
public:
MyClassa(){
};
~MyClassa(){};
void printt()
{
cout << "b";
}
void b()
{
c();
printt();
}
private:
...
};
By the rules above, I should be able to call 'c()' from person class in 'b()' ('b()' is function of Student which is virtual brother of 'Person class').
But I get an error:
Error 1 error C3861: 'c': identifier not
found c:\users\micha\onedrive\מסמכים\visual studio
2013\projects\project7\project7\student.h 21 1 Project7

This is because the "c()" function is not declared in the base class "father" and your class "MyClassa" derives only from "father".
Consequently, an object of class "MyClassa" will not contain any function "c()".
An object of a class deriving from "MyClasst" (as well as an object deriving from both "MyClassa" and "MyClasst" will have it).
If you want to have your code compiling, you must add a declaration of "c()" in the parent class. Add the line "virtual void c() = 0;" in the class "father" - then will compile. Live example here: http://rextester.com/OBBC17077

There is no method c() in MyClassa directly nor inherited from father. There is a method c() in MyClasst, but the two classes have no relation apart from inheriting both from father, but that doesnt allow them to call methods from each other.
Imho the analogy with the so called "parent class" and "child classes" does not make much sense and only leads to confusion. It doesnt make sense to say "a child is-a parent", but thats what (public) inheritance actually is. I would advice you to forget about the term "brother class". It doesnt help you to understand anything. And btw the error you get has little to do with the virtual inheritance. You would get the same error with public inheritance.

Related

How to execute a function out of an included class

I got two classes separated in four files. The main class includes a sub class and needs to execute functions of it (not shown in the minimal example code). What I want to do is to execute a function of the main class in the scope of the subclass.
I think some ideas would be to inherit the functions in the sub class but I could not figure out how to do this.
MainClass.cpp
#include "MainClass.hpp"
void MainClass::mainCallback() {
std::cout << "[mainCallback] executed" << std::endl;
}
void MainClass::subCallback() {
std::cout << "[subCallback] executed" << std::endl;
}
int main() {
MainClass mainClass;
mainClass.mainCallback();
SubClass subClass;
subClass.activateSubClass();
return 0;
}
MainClass.hpp
#pragma once
#include "SubClass.hpp"
#include <iostream>
class MainClass{
public:
void mainCallback();
void subCallback();
};
SubClass.cpp
#include "SubClass.hpp"
void SubClass::activateSubClass(){
mainClass.subCallback(); //TODO call this function from this scope
}
SubClass.hpp
#pragma once
class SubClass{
public:
void activateSubClass();
};
The error in SubClass.cpp is of course:
error: use of undeclared identifier 'mainClass'
Just subclass the subclass:
class SubClass: public MainClass {
public:
void activateSubClass();
};
This (public) way the SubClass makes all methods of MainClass callable in SubClass instances. You could also private inherit. That way only activateSubClass() 'ld be callable.
In activateSubClass you can call directly the methods of the parent class:
void SubClass::activateSubClass(){
mainClass.subCallback(); //TODO call this function from this scope
}
Don't forget to include MainClass.hpp in SubClass.hpp
You try to call a MainClass.subCallback() without having an instance of MainClass. According to me, this is the typical use case for static methods.
Then, I think you make your #include directives the wrong way. Indeed, MainClass does not seem to need to know SubClass but the opposite is true. I think it is better to include MainClass.hpp in SubClass.hpp. This will solve your circle dependencies problem.And you can write your main() function in another file.
EDIT: Example
MainClass.hpp:
#pragma once
class MainClass
{
public:
void mainCallback();
static void subCallback(); // mak it static to be able to call it without an instance of the class
};
MainClass.cpp:
#include "MainClass.hpp"
#include <iostream>
void MainClass::mainCallback()
{
std::cout << "[mainCallback] executed" << std::endl;
}
void MainClass::subCallback()
{
std::cout << "[subCallback] executed" << std::endl;
}
SubClass.hpp:
#pragma once
class SubClass
{
public:
void activateSubClass();
};
SubClass.cpp:
#include "SubClass.hpp"
#include "MainClass.hpp" // MainClass inclusion
void Suclass::activateSubClass()
{
MainClass::subCallback(); // Call of the static method
}
main.cpp:
#include "MainClass.hpp"
#include "SubClass.hpp"
int main()
{
MainClass mc;
mc.mainCallback();
SubClass sc;
sc.activateSubClass(); // Will call MainClass::subCallback()
return 0;
}
I hope it can help you.

Having trouble with inheritance in implementation of C++ factory method

Fairly new to design patterns, maybe I've missed the answered question already. I'm having trouble practicing the factory design pattern due to an inheritance issue.
This is the base class
#ifndef FACTORY_H
#define FACTORY_H
#include <iostream>
#include "truckfactory.h"
class factory{
public:
std::string typeOfCar;
factory(){}
virtual void identifyCar(){
std::cout << "This car is a " + typeOfCar << std::endl;
}
truckfactory* createTruck(){
return new truckfactory();}
};
#endif
And this is the subclass of the base factory class.
#ifndef TRUCKFACTORY_H
#define TRUCKFACTORY_H
#include "factory.h"
class truckfactory : public factory{
public:
truckfactory(){
std::cout <<"TruckFactory made"<<std::endl;
typeOfCar = "truck";
}
};
#endif
Trying to implement as such
#include "factory.h"
int main(){
factory carFactory;
truckfactory* truck;
truck = carFactory.createTruck();
carFactory.identifyCar();
truck->identifyCar();
return 0;
}
However I run into the following issues
./truckfactory.h:5:29: error: expected class name
class truckfactory : public factory
^
./truckfactory.h:11:13: error: use of undeclared identifier 'typeOfCar'
typeOfCar = "truck";
^
factorytest.cpp:10:12: error: no member named 'identifyCar' in 'truckfactory'
truck->identifyCar();
I was looking around at other inheritance issues, but I couldn't find one that solves what I'm looking at.
Thanks for the help, and sorry if it's a repost
There are a few things to consider:
The reason your code won't compile is due to its structure. You can't (or shouldn't) have factory.h include truckfactory.h, which then includes factory.h. The circular dependency will cause you problems. The normal way of handling this is to forward declare truck_factory like this:
#ifndef FACTORY_H
#define FACTORY_H
#include <iostream>
class truck_factory;
class factory{
public:
std::string typeOfCar;
factory(){}
virtual void identifyCar(){
std::cout << "This car is a " + typeOfCar << std::endl;
}
truckfactory* createTruck(); //Note definition must be in c++ file
};
#endif
Conceptually your factory should build objects, not other factories. For example, you might have a class factory which knows how to build trucks, car, motorbikes etc. To do this you would want to define a vehicle class and then a factory which can build the correct class based on the type passed in. Something like:
class Vehicle {
public:
virtual std::string typeOfCar() const = 0;
void identifyCar() {
std::cout << "This car is a " + typeOfCar << std::endl;
}
};
class Factory {
public:
Vehicle* create_vehicle(const std::string& type); // need to somehow specify what type you want to create.
};
class Truck : public Vehicle {
virtual std::string typeOfCar() const { return "truck"; }
};
The create_vehicle function would need to be defined in a cpp file to return various vehicle types.

Access specifier toward scoped base method

In the following complete program:
#include <vector>
class Derived : private std::vector<int> {
public:
void f();
};
void Derived::f() {
Derived d;
d.std::vector<int>::push_back(0);
}
int main() {
Derived d;
d.f();
}
the line
d.std::vector<int>::push_back(0);
can be replaced by
d.vector<int>::push_back(0);
and the compilation would complete w/o warning both in gcc 7 and clang 6.
I don't understand why the std:: part of the scope resolution is optional, since there's no using namespace std declaration.
As others already mentioned:
Do not inherit from STL!
See this and this and read Effective c++ book.
Apart from the derivation from STL, it could be an everyday problem. I think you are searching for how qualified name lookup works.
Consider the following code
#include <iostream>
#include <string>
namespace myNamespace {
namespace nested {
class base {
protected:
std::string print() { return "Fantastic"; };
static const int four= 4;
};
}
}
class derived : private myNamespace::nested::base
{
public:
// no need to extra qualify base class methods, since derived access the scope of the base class
std::string doStuff() { return print() + std::to_string(four); };
};
int main()
{
derived d;
std::cout << d.doStuff();
}
It has the same structure, deriving from something that is a part of a namespace. As you noticed, in the derived there is no need to extra qualify the print method. However, the following is completely legal call in the doStuff method:
print();
base::print();
myNamespace::nested::base::print();
Note that simply nested::base::print(); is not legal - myNamespace should be used.
Ps. I compiled with MSVC 143, and always produced this output:
Fantastic4

Error with dynamic_cast

I'm having problems with my code with dynamic_cast. I have spent many hours trying to find a solution for this, but I still don't find the answer. I read that the problem could be because I didn't write forward declarations but I have already done that and still with the same problem.
Abstract class
#include "CRoute.h"
class CScreen
{
protected:
CRoute* m_pRoute;
public:
virtual ~CScreen();
virtual void connecToRoute(CRoute* route) = 0;
virtual void drawRoute() = 0;
};
Derived class
#include "CScreen.h"
class CGUIScreen : public CScreen
{
public:
void drawRoute();
void connecToRoute(CRoute* route);
};
Derived class
#include "CScreen.h"
class CCRTScreen : public CScreen
{
public:
void drawRoute();
void connecToRoute(CRoute* route);
};
Base Class
#include <string>
#include <iostream>
using namespace std;
class CScreen;
class CCRTScreen;
class CGUIScreen;
class CWaypoint
{
public:
CWaypoint();
void print(int format, CScreen* screenType);
};
Derived class
#include <iostream>
#include <string>
#include "CWaypoint.h"
using namespace std;
class CScreen;
class CCRTScreen;
class CGUIScreen;
class CPOI : public CWaypoint
{
public:
void print(int format, CScreen* screenType);
};
Method of CPOI
void CPOI::print(int format, CScreen* screenType)
{
if(dynamic_cast<CGUIScreen*>(screenType)) ---> Here is the error <<----
{
cout << "printing POI GUI " << endl;
}
else if(dynamic_cast<CCRTScreen*>(screenType)) ---> Here is the error <<----
{
cout << "printing POI CRT " << endl;
}
}
And the error I'm getting is the next one
..\myCode\CWaypoint.cpp:184:41: error: cannot dynamic_cast 'screenType' (of type 'struct CScreen*') to type 'struct CGUIScreen*' (target is not pointer or reference to complete type)
..\myCode\CWaypoint.cpp:184:44: error: expected unqualified-id before ')' token
..\myCode\CWaypoint.cpp:188:46: error: cannot dynamic_cast 'screenType' (of type 'struct CScreen*') to type 'struct CCRTScreen*' (target is not pointer or reference to complete type)
I read that the problem could be because I didn't write forward
declarations but I have already done that and still with the same
problem.
Quite the contrary; your forward declarations are what causes the errors.
A forward declaration, such as your class CScreen; line, simply tells the compiler: "There is a class called 'CScreen'. I'll give you more details later, but for now just keep in mind that this is a valid class name, OK?"
The compiler can then do very basic things with that class name; for example, it will accept pointer or reference declarations with it. That's why your print(int format, CScreen* screenType) line works. You don't need to know anything about CScreen other than its name to declare a pointer to it.
But how is the compiler supposed to accept a dynamic_cast with the class name? It does not really know anything about the class. In particular, it does not know that CGUIScreen or CCRTScreen are derived from CScreen. That's why at the point where you use dynamic_cast, the full class definitions are needed.
The header files for CWaypoint and CPOI (possible called waypoint.h and point.h?), can thus safely use forward declarations. As you correctly did:
waypoint.h:
class CScreen;
class CCRTScreen;
class CGUIScreen;
class CWaypoint
{
public:
CWaypoint();
void print(int format, CScreen* screenType);
};
point.h:
class CScreen;
class CCRTScreen; // not necessary but not invalid
class CGUIScreen; // not necessary but not invalid
class CPOI : public CWaypoint
{
public:
void print(int format, CScreen* screenType);
};
The implementation files, however, (possible called waypoint.cpp and point.cpp?), require the full definitions when you use a dynamic_cast:
point.cpp:
#include "point.h"
#include "screen.h"
#include "gui_screen.h"
#include "crt_screen.h"
#include <iostream>
using std::cout;
using std::endl;
void CPOI::print(int format, CScreen* screenType)
{
if(dynamic_cast<CGUIScreen*>(screenType))
{
cout << "printing POI GUI " << endl;
}
else if(dynamic_cast<CCRTScreen*>(screenType))
{
cout << "printing POI CRT " << endl;
}
}
By the way, it seems that CWaypoint should actually be an abstract base class, and that it possibly doesn't need an implementation file at all:
point.h:
class CScreen;
class CWaypoint
{
public:
virtual ~CWaypoint() {}
virtual void print(int format, CScreen* screenType) = 0;
};
P.S: If I may say so, I think your class names are confusing. A "Point" is definitely something more general than a "Waypoint", yet the inheritance relationship is exactly vice versa. Also, consider getting rid of Hungarian Notation. Just call your classes Screen instead of CScreen etc.
What the error message is telling you is that it does not know what the definition of CScreen or any of the derived classes are because you have forward declared them but not included their definitions.
Instead of
class CScreen;
class CCRTScreen;
class CGUIScreen;
Use
#include "CCRTScreen.h"
#include "CGUIScreen.h"

Error C2512 'DerivedClass' : no appropriate default constructor available

I am having an issue with this error, and adding a default constructor does not fix it. compiling without default constructors produces the error, compiling with default constructors produces the error. I've been searching online for hours but found nothing. Here's a quick example of my code (The actual code is rather long):
//Header.h
using namespace std;
class BaseClass;
class DerivedClass;
BaseClass *MyClass = new DerivedClass;
class BaseClass
{
virtual void myFunction()
{
cout << "Base Class";
}
};
class DerivedClass : public BaseClass
{
void myFunction()
{
cout << "Derived Class";
}
};
//Main.cpp
#include <iostream>
#include "Header.h" //I believe this gives Header.h access to iostream
//I believe it cause it works
using namespace std;
int main()
{
cout << "Hello";
}
The error is in Header.h, Main is only there to give Header.h access to iostream.
As I said I've look for HOURS. And haven't found any ways to fix the error:
Error C2512: 'DerivedClass' : no appropriate default constructor available
Why you need this in header file?
Baseclass *MyClass = new DerivedClass;
Clearly compiler is looking for definition of derived class and not found till this line executes.
Move it after implementation of derived class or in main.
Baseclass *MyClass = new DerivedClass;
should come after the definition of the classes, i.e. end of file
P.S. your comment in the code (about giving access to iostream) is correct. But consider it is not good practice. Header files should compile with no requisites on different inclusions.
instantiating the MyClass object within the .h is no good practic either.
You program is totally invalid.
You allocate memory for class DerivedClass but it is not defined yet.
Baseclass *MyClass = new DerivedClass;
You use standard output stream
cout << "Base Class";
but it is not declared yet because there is no the corresponding header where the stream is declared.
The definition of function myFunction has no sense because it has private access control and may not be called outside methods of the class itself but there is no such a method.
The correct code could look the following way
//Header.h
#include <iostream>
using namespace std;
class BaseClass
{
public:
virtual void myFunction() const
{
cout << "Base Class";
}
};
class DerivedClass : public BaseClass
{
public:
void myFunction() const
{
cout << "Derived Class";
}
};
//Main.cpp
#include <iostream>
#include "Header.h" //I believe this gives Header.h access to iostream
//I believe it cause it works
using namespace std;
Baseclass *MyClass = new DerivedClass;
int main()
{
cout << "Hello";
}