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"
Related
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.
Like many people asking this question, I am very new to C++ and I can't wrap my head around this error:
Dollar.h:4:31: error: expected class-name before '{' token
class Dollar: public Currency {
These are my files
main.cpp
#include <iostream>
#include "Dollar.h"
using namespace std;
int main() {
Dollar * d = new Dollar();
d->printStatement();
return 0;
}
Currency.cpp
#include <iostream>
#include "Currency.h"
using namespace std;
class Currency {
public:
virtual void printStatement() {
cout << "I am parent";
}
};
Currency.h
#ifndef CURRENCY_H
#define CURRENCY_H
class Currency {
public:
virtual void printStatement();
};
#endif
Dollar.cpp
#include <iostream>
using namespace std;
void printStatement() {
cout << "I am dollar";
}
Dollar.h
#ifndef DOLLAR_H
#ifndef DOLLAR_H
class Dollar : public Currency {
public:
void printStatement();
};
#endif
Thank you so much for your time and any help is much appreciated.
The error says that the name of a class was expected between : public and { here:
class Dollar : public Currency {
^^^^^^^^
Currency is not a name of a class, because you haven't defined such class. Yes, you have defined such class in files Currency.cpp and Currency.h, but not in the file Dollar.h where that error occurs.
Solution: The class Currency has to be defined first before it can be used as a base class. Like so:
// class is defined first
class Currency {
public:
virtual void printStatement();
};
// now Currency is a class and it can be used as a base
class Dollar : public Currency {
public:
void printStatement();
};
Since a class must be defined in all source files where it is used, and the definition must be identical across all source files, it is often useful to define the class in a separate "header" file, such as you have done. In such case you can simply include that header in stead of writing the definition repeatedly in each source file:
#include "Currency.h"
Currency.cpp contains two definitions for the class Currency. Once in the header that is included, and then second time after that. You may not have multiple definitions for the same class in a single source file.
Solution: Remove the class definition from Currency.cpp. Instead only define the member function:
void Currency::printStatement() {
//...
}
Finally, you haven't defined Dollar::printStatement. You've defined printStatement, which is not the same thing.
In my case, I had two classes with same name but in two different namespaces.
So, changing the base class to something different solved the problem.
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.
I am attempting to create an poptart vending machine program within c++ and i am trying to use the this keyword, however i am always getting an error stating 'this' may only be used inside a nonstatic member function. Below is a part of the code that i am getting one such issue in
Code:
#include <iostream>
#include "HasCredit.h"
using namespace std;
void insertMoney(int money)
{
cout<<"You inserted: " << money;
money = money+this->currentContext->getStateParam(Credit);
this->currentContext->setStateParam(Credit,money);
cout<< "Total: "<<money<<endl;
this->currentContext->setState(Has_Credit);
}
Any suggestions onto why i am getting this error will be most appreciated. Cheers.
Edit: the insertMoney method is within a class called HasCredit.
Edit2: member declarations are now made outside of the constructor
Edit3: Added state class declaration
The Class Definition Code is Below:
#include <iostream>
#include "State.h"
#include "StateContext.h"
using namespace std;
class HasCredit: public State
{
HasCredit (StateContext* Context) : State(Context) {
}
void insertMoney(int);
void MakeSelectionCoating(int);
void MakeSelectionFilling(int);
void moneyRejected(void);
void addPopTarts(int);
void dispense(void);
};
The state class declaration code is shown Below:
#include <iostream>
#include "Transition.h"
using namespace std;
class State: public Transition
{
protected:
StateContext* currentContext;
public:
State(StateContext* Context);
};
The this pointer is only valid inside a class. Your insertMoney function is not declared to be in a class. See http://www.learncpp.com/cpp-tutorial/87-the-hidden-this-pointer/.
In your definiton of insertMoney (in the code, not the class), you do not declare it to be a member of hasCredit. You need to use void hasCredit::insertMoney instead.
You probably want to attach insertMoney to a class. Try ClassName::insertMoney in your definition.
The error is telling you exactly why you're getting it.
The solution is to fix the definition of what you intend to be a member function, so that the compiler knows it is a member function. Like this:
// vv THIS WAS MISSING
void HasCredit::insertMoney(int money)
{
...
Your member declarations shown in the question are also in the wrong place. They need to be inside the class body, but outside the constructor. When overriding virtual member functions, you may want to show that to readers by using the virtual and override keywords. (Note, override only works if you have a new, C++11 compiler. For older compilers, use a comment /* override */ instead)
class HasCredit: public State
{
HasCredit (StateContext* Context) : State(Context) { }
// vv THIS....................CANNOT BE INSIDE HERE ^^
virtual void insertMoney(int) override;
...
};
You probably want some of your members to be public as well.
There are a few things wrong:
class definition:
#include <iostream>
#include "State.h"
#include "StateContext.h"
using namespace std;
class HasCredit: public State
{
HasCredit (StateContext* Context) : State(Context) {
}
void insertMoney(int);
void MakeSelectionCoating(int);
void MakeSelectionFilling(int);
void moneyRejected(void);
void addPopTarts(int);
void dispense(void);
};
Note that the methods should be declared outside of the constructor definition.
For the implemenation:
#include <iostream>
#include "HasCredit.h"
using namespace std;
void HasCredit::insertMoney(int money)
{
cout<<"You inserted: " << money;
money = money+this->currentContext->getStateParam(Credit);
this->currentContext->setStateParam(Credit,money);
cout<< "Total: "<<money<<endl;
this->currentContext->setState(Has_Credit);
}
The method must be qualified with the name of the class... otherwise it would be considered a definition of a function... and a function does not have a this
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";
}