Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am trying to change a subclass values Capacity, RentRate and RentMin using operation overloading. I'm newish to c++, come from java.
I want to create the objects
VanIn Van7("Large", 200, 2.0);
ManVanIn ManVan8("Abc", 99999, "Medium", 100, 1.0);
ManVan8 = Van7;
Making ManVan8 values change from "Medium, 100, 1.0" to "Large, 200, 2.0" but I keep getting a object qualifer error at the operations overload method
using namespace std;
class AbstractVan {
private:
int RentMin;
string Drivername;
long DLno;
string Capacity;
float RentRate;
public:
AbstractVan(string Drivername, long DLno, string Capacity, int RentMin, float RentRate) : Capacity(Capacity), RentMin(RentMin), RentRate(RentRate), DLno(DLno), Drivername(Drivername) {}
void setCapacity(string cap) { Capacity = cap; }
void setRentRate(float rate) {RentRate = rate;}
void setRentMin(int min) {RentMin = min;}
string getCapacity() { return Capacity; }
float getRentRate() { return RentRate; }
int getRentMin() { return RentMin; }
virtual void print() = 0;
};
Derived class from AbstractVan
class VanIn : public AbstractVan {
public:
VanIn(string Capacity, int RentMin, float RentRate) : AbstractVan(Capacity, RentMin, RentRate) {}
AbstractVan(string Drivername, long DLno, string Capacity, int RentMin, float RentRate) : Capacity(Capacity), RentMin(RentMin), RentRate(RentRate), DLno(DLno), Drivername(Drivername) {}
Derived class from VanIn
class ManVanIn : public VanIn {
private:
string Drivername;
int DLno;
public:
ManVanIn(string Drivername, long DLno, string Capacity, int RentMin, float RentRate) : VanIn(Drivername, DLno, Capacity, RentMin, RentRate){}
void print() { cout << "Drivername " << this->Drivername << " Registration " << this->DLno << " - " << getCapacity() << endl; }
~ManVanIn() {cout << "Destroy ManVanIn" << endl;}
void operator = (const VanIn &D) {
setCapacity(D.getCapacity());
setRentRate(D.getRentRate());
setRentMin(D.getRentMin());
}
};
Entry
int main()
{
VanIn Van7("Large", 200, 2.0);
ManVanIn ManVan8("Abc", 99999, "Medium", 100,1.0);
ManVan8 = Van7;
ManVan8.print();
system("pause");
return 0;
};
First of all things, as you will see later on, it's good practice to define getters with const qualifier. Otherwise it cannot be called on const object - I will get into that later.
string getCapacity() const { return Capacity; }
float getRentRate() const { return RentRate; }
int getRentMin() const { return RentMin; }
By using const qualifier you declare, that these methods only read from object and they don't change anything within the object. By following this 'rule' print() should be declared with const qualifier as well:
virtual void print() const = 0;
Second thing is if you have at least one virtual method, destructor should be virtual as well.
virtual ~AbstractVan() = default;
Next problem is in your VanIn class. Definition of constructor is wrong. VanIn is derived class from AbstractVan, therefore before creating VanIn, base class (in this case AbstractVan) must be created. Since AbstractVan doesn't have default constructor you must call parametric one (which accepts 5 arguments) in initialization section. Like this:
VanIn(string Capacity, int RentMin, float RentRate)
: AbstractVan(/* 5 parameters MUST be here */) { }
Don't forget what order of parameters is in AbstractVan constructor(e.g. it won't accept float if it expects string).
Note: you might want to use const string& in this constructor instead of string. const string& means that it is read-only reference (no unnecessary copying).
Next issue is in ManVanIn class. I don't see use of private variables. Same thing will be saved in AbstractVan after its constructor is called. Also when you call constructor of ManVanIn you try to call VanIn constructor with invalid number of arguments. Your declared version expects 3, and you give 5.
Next one is not a issue but is a good practice. When you override virtual functions use override specifier, like this:
void print() const override { /* ... */ }
It is good practice because if you try to override function which is not virtual your program won't compile (you avoid a lot of mistakes by using this). For example if you declared print function in Abstract as I did and you try override function like this:
double print() override { /* ... */ }
or even like this
void print() override { /* ... */ }
compiler will warn you that you are overriding function which is not virtual. In first case it should be clear, you didn't declare print() member function returning double. In second case it is because of missing const qualifier.
The reason why getters should be const lies here:
void operator = (const VanIn &D) {
setCapacity(D.getCapacity());
setRentRate(D.getRentRate());
setRentMin(D.getRentMin());
}
Your operator = overload accepts one parameter which is const reference to VanIn object. What you say here is that you won't change VanIn object within the body of this function. Therefore compiler cannot call non-const methods on const objects. If you miss const qualifier in these cases your program won't even compile (it should give error about discarding cv-qualifier).
Related
I am using C++ 14 with clang on MacOS Sierra. I want to enforce a rule by design. Following is the rule.
I have a member variable in my class say:
unsigned int m_important_num;
There are 4 methods in my class.
fun1();
fun2();
fun3();
fun4();
Objective:
I want only fun2() to be able to change the value of m_important_num.
Question:
Is it possible to make it compiler error if any method other than fun2() changes the variable?
One possible way is to declare it const somehow empower fun2() to change const variables? Is this a good solution? Or are their any better solutions?
Secondary question:
Is it a wrong design to try do such a thing?
Sort of, with additional layer:
class S1 {
public:
void fun2() { /*Modify m_important_num */ }
unsigned int getImportantNum() const { return m_important_num;}
private:
unsigned int m_important_num;
};
class S2 : private S1
{
public:
void fun1();
using S1::fun2; // or void fun2() {S1::fun2();}
void fun3();
void fun4();
};
As Yakk commented, if func2 need access to S2 members, CRTP can solve that:
template <typename Derived>
class S1 {
public:
void fun2() { asDerived().foo3(); /*Modify m_important_num */ }
unsigned int getImportantNum() const { return m_important_num;}
private:
Derived& asDerived() { return stataic_cast<Derived&>(*this); }
private:
unsigned int m_important_num;
};
class S2 : private S1<S2>
{
// friend class S1<S2>; // If required.
public:
void fun1();
using S1::fun2; // or void fun2() {S1::fun2();}
void fun3();
void fun4();
};
Encapsulate it down. Put m_important_num in its own class. Aggregate it in your existing class. Have a getter for it. Then put fun2() as a member function of your inner class.
I little variant (if I understand correctly) of the Jeffrey solution: put the variable in an inner class and make it private; create a public getter and make func2() friend to the inner class.
I mean
struct foo
{
int f1 () { return b0.getVal(); }; // you can read `val` everywhere
void f2 () { b0.val = 42; }; // you can write `val` in f2()
void f3 () { /* b0.val = 42; ERROR ! */ }; // but only in f2()
class bar
{
private:
int val = 24;
public:
int getVal () { return val; }
friend void foo::f2 ();
};
bar b0;
};
In other words: friend is your friend.
If you want to prevent a method from modifying any member in the class you can use the trailing const identifier:
class something{
private:
unsigned int var;
public:
void fun1() const;
void fun2();
void fun3() const;
void fun4() const;
}
Here, only fun2() will be able to modify the variable.
I know there are lots of good answers, but there is also an option that you sort of alluded to in your question:
One possible way is to declare it const somehow empower fun2() to change const variables?
#include <iostream>
using uint = unsigned int;
class Test
{
const uint num;
public:
Test(uint _num)
:
num(_num)
{}
uint get_num() const
{
return num;
}
void can_change_num(uint _new_num)
{
uint& n(const_cast<uint&>(num));
n = _new_num;
}
void cant_change_num(uint _new_num)
{
// num = _new_num; // Doesn't compile
}
};
int main()
{
Test t(1);
std::cout << "Num is " << t.get_num() << "\n";
t.can_change_num(10);
std::cout << "Num is " << t.get_num() << "\n";
return 0;
}
Produces
Num is 1
Num is 10
You already got lots of good answers to your primary question. I'll try to address the secondary one.
Is it a wrong design to try do such a thing?
It's hard to say w/o knowing more about your design. In general anything like this detected during a code review would raise a big red flag. Such a protection makes sense in a case of a big class with convoluted logic/implementation. Otherwise why would you like to go an extra mile and make your code much more complicated? The fact you seek for this can indicate your class became unmanageable.
I'd recommend to consider splitting it to smaller parts with better defined logic where you won't worry such mistakes can happen easily.
I've got an assignment, some demands were made such as making an abstract baseclass for two types of questions which will be subclasses, and another demand is that all three classes have to have two constructors and that only the destructors may be empty.
So I did this in the .cpp of Question(baseclass):
Question::Question(string question)
{
this->question = question;
}
Question::Question()
{
this->question = "N/A";
}
And in one of the subclasses called "MultipleAnswerQuestion" I try doing this:
MultipleAnswerQuestion::MultipleAnswerQuestion(string question, string alternatives[],
int alternativeAmount, int correctAnswer):Question(question)
{
for(int i=0; i<alternativeAmount; i++){
this->alternatives[i] = alternatives[i]; //string
}
this->alternativeAmount = alternativeAmount; //int
this->correctAnswer = correctAnswer; //int
}
MultipleAnswerQuestion::MultipleAnswerQuestion()
{
for(int i=0; i<alternativeAmount; i++){
this->alternatives[i] = ""; //string
}
this->alternativeAmount = NULL; //int
this->correctAnswer = NULL; //int
}
And an error comes up about the bottom constructor of MultipleAnswerQuestion, saying:
"IntelliSense: class "Question" has more than one default constructor"
What's wrong?? How do I solve this?
Filling out the constructors and having two of them is a demand, so I can't just remove one.
EDIT
Class declarations:
class Question
{
public:
Question();
Question(string question = "N/A");
virtual ~Question();
void setQuestion(const string &question);
string getQuestion() const;
void print() const;
virtual void printSpec() const=0;
private:
string question;
};
And MultipleAnswerQuestion:
const int MAX = 6;
class MultipleAnswerQuestion :
public Question
{
public:
MultipleAnswerQuestion();
MultipleAnswerQuestion(string question, string alternatives[], int alternativeAmount, int correctAnswer);
virtual ~MultipleAnswerQuestion();
void printSpec() const;
void setCorrectAnswer(int correctAnswer);
void setAlternative(int alternativeNr, string alternative);
private:
int correctAnswer;
string alternatives[MAX];
int alternativeAmount;
};
You have two constructors, one default and one taking a string. However you've declared the string constructor with a default parameter, so if you try to construct one without any parameters there are two that could potentially be used. The compiler complains because it can't use both and doesn't have a rule to pick one over the other.
Either delete the default constructor, or remove the default on the string parameter.
I am just starting my adventure in the land of C++, so this may be a silly question. I am getting the following error from my compiler.
Run.cc:56: error: no matching function for call to ‘sphereDetect::getArrayPtr() const’
/spheredetect.hh:18: note: candidates are: const G4long (* sphereDetect::getArrayPtr())[36][72][60]
my Run.hh is:
#include "spheredetect.hh"
#include "G4Run.hh"
#include "globals.hh"
class G4Event;
/// Run class
///
class Run : public G4Run
{
public:
Run();
virtual ~Run();
// method from the base class
virtual void Merge(const G4Run*);
void AddEdep (G4double edep);
// get methods
G4double GetEdep() const { return fEdep; }
G4double GetEdep2() const { return fEdep2; }
private:
G4double fEdep;
G4double fEdep2;
sphereDetect scatter;
};
my Run.cc is:
#include "Run.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Run::Run()
: G4Run(),
fEdep(0.),
fEdep2(0.),
scatter()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Run::~Run()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Run::Merge(const G4Run* run)
{
const Run* localRun = static_cast<const Run*>(run);
fEdep += localRun->fEdep;
fEdep2 += localRun->fEdep2;
arr* scatterPointer = localRun->scatter.getArrayPtr();
scatter.sphereMerge(scatterPointer);
G4Run::Merge(run);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Run::AddEdep (G4double edep)
{
fEdep += edep;
fEdep2 += edep*edep;
}
and my sphereDetect.hh is:
typedef G4long arr[36][72][60];
class sphereDetect
{
public:
sphereDetect();
~sphereDetect();
const arr* getArrayPtr() {return &scatterArray;}
void sphereMerge(arr*);
void createHit(G4ThreeVector,G4double);
protected:
void storeHit(G4int,G4int,G4int);
G4int findAngNS(G4ThreeVector);
G4int findAngEW(G4ThreeVector);
G4int findEnergy(G4double);
void sphereSave();
private:
G4long scatterArray[36][72][60];
};
I am fairly lost as to how to resolve this. Is it in the way i construct or call the sphereDetect class? The one thing that is certain is that the input for the Run.Merge is required to be that input(based on the previous code).
Any help is greatly appreciated,
Will
You're short a const.
const arr* getArrayPtr() {}
Means "this returns a const pointer".
const arr* getArrayPtr() const {}
Means "this returns a const pointer, and can be called on a const object". Otherwise, the compiler can't tell that getArrayPtr() doesn't want to modify the object on which it's called.
Since localRun is const, it's member localRun->scatter is const, too.
The compiler is looking for a definition of getArrayPtr() which declares that it will not modify the object and thus is safe to call on a const object. This is done by putting the const after the rest of the function signature, just like G4double GetEdep() const has it.
I created a singleton class
class AreaDataRepository {
private:
AreaDataRepository();
AreaDataRepository(const AreaDataRepository& orig);
virtual ~AreaDataRepository();
Way onGoingWay;
public:
static AreaDataRepository& Instance()
{
static AreaDataRepository singleton;
return singleton;
}
void SetOnGoingWay(Way onGoingWay);
Way const & GetOnGoingWay() const;
};
void AreaDataRepository::SetOnGoingWay(Way onGoingWay) {
this->onGoingWay = onGoingWay;
}
Way const & AreaDataRepository::GetOnGoingWay() const {
return onGoingWay;
}
header file of Way
class Way {
private:
std::string id;
std::string name;
public:
Way();
Way(const Way& orig);
virtual ~Way();
void SetName(std::string name);
std::string const & GetName() const;
void SetId(std::string id);
std::string const & GetId() const;
};
Then i'm created a Way object and set vales of id and name.
Way wayNode;
wayNode.SetId("123");
wayNode.SetName("jan")
AreaDataRepository::Instance().SetOnGoingWay(wayNode);
After assign OngoingWay accessing it from another class.
std::cout << AreaDataRepository::Instance().GetOnGoingWay().GetId();
the vale is not printing.
I'm going psychic here.... and I divine that your implementation of SetId is like this:
void SetId(std::string id) { id = id; }
that does not set the member variable, that sets the parameter to itself. And since your constructor most likely set the member variable id to "" you're printing empty strings. Either change the name of the parameter (to newId for example) to avoid the conflict or change the implementation to:
void SetId(std::string id) { this->id = id; }
As proof of this claim here's the result for the first version, as you see it prints nothing. And here is the result for the second, as you can see it prints the number.
The problem boils down to this: you have function parameter names that are the same as the name of your member variables and the function parameters are shadowing/hiding the member variables.
The only place this cannot happen is in a constructor's initialization list:
class Foo {
int x;
public:
Foo(int x): x(x) {} // <-- this works
void SetX(int x) { x = x; } // <-- this won't the parameter is hiding the member variable
};
Demo for the above snippet
std::cout is buffered in most implementations, if not in all. That means, the stream will wait for you to end a line before writing out any data. So, you can easily fix this by changing your output statement to
std::cout << AreaDataRepository::Instance().GetOnGoingWay().GetId() << std::endl;
I'm using a library (libtcod) that has an A* pathfinding algorithm. My class inherits the callback base class, and I implement the required callback function. Here is my generic example:
class MyClass : public ITCODPathCallback
{
...
public: // The callback function
float getWalkCost(int xFrom, int yFrom, int xTo, int yTo, void *userData ) const
{
return this->doSomeMath();
};
float doSomeMath() { // non-const stuff }
};
I found a number of examples using const_cast and static_cast, but they seemed to be going the other way, making a non-const function be able to return a const function result. How can I do it in this example?
getWalkCost() is defined by my library that I cannot change, but I want to be able to do non-const things in it.
The best solution depends on why you want to do non-const stuff. For example, if you have a cache of results that you want to use to improve performance, then you can make the cache be mutable, since that preserves the logical constness:
class MyClass : public ITCODPathCallback
{
...
public: // The callback function
float getWalkCost(int xFrom, int yFrom, int xTo, int yTo, void *userData ) const
{
return this->doSomeMath();
};
float doSomeMath() const { // ok to modify cache here }
mutable std::map<int,int> cache;
};
Or perhaps you want to record some statistics about how many times the getWalkCost was called and what the maximum x value was, then passing a reference to the statistics may be best:
class MyClass : public ITCODPathCallback
{
...
public:
struct WalkStatistics {
int number_of_calls;
int max_x_value;
WalkStatistics() : number_of_calls(0), max_x_value(0) { }
};
MyClass(WalkStatistics &walk_statistics)
: walk_statistics(walk_statistics)
{
}
// The callback function
float getWalkCost(int xFrom, int yFrom, int xTo, int yTo, void *userData ) const
{
return this->doSomeMath();
};
float doSomeMath() const { // ok to modify walk_statistics members here }
WalkStatistics &walk_statistics;
};
You can hack it this way:
return const_cast<MyClass*>(this)->doSomeMath();
Of course this won't be considered good design by most people, but hey. If you prefer you can instead make doSomeMath() const, and mark the data members it modifies as mutable.