I am a new c++ programmer, and have learned some java before. I am do my assignment. And I just could not get my heard around this problem.
class A{
private:
bool test;
public:
void anotherSetTest();
void setTest();
A();
};
void Globle_scope_function(A a){
a.setTest(true);
}
A::A(){
test = false;
}
void A::setTest(bool foo){
test = foo;
}
void A::anotherSetTest(){
Globle_scope_function(*this);
}
int main(){
A a;
a.anotherSetTest();
cout<<a.getTest()<<endl;//It suppose to output true, but why does it output false.
system("pause");
return 0;
}
When I use visual studio to debug, it tells me that the object has gone out of scope. How do I solve it... :-< . Edit it to MWV.
Calling Globle_scoop_function(*this); takes a deep copy of *this to the function parameter a. It's that object that goes out of scope at the end of Globle_scoop_function. The object *this remains unmodified.
One remedy would be to change the prototype to void Globle_scoop_function(A& a){. Note the & which denotes a reference. You then modify the a in main() through that reference.
The fact that all the various instances of A in your code are all called a only adds to the confusion.
Related
I have a structure in my cpp program. Function pointer is one of its members. When this structure is passed to a function-in-dll, it assigns a function to this pointer.
So my main program does not know if the dll has assigned a function or not. My aim is to call the function through pointer only if it is assigned through dll.
I have made a minimal-working code of the situation:
#include <stdio.h>
typedef struct _test{
void (*foo)(int a){};
}test;
void bar(int b)
{
printf("you called bar\n");
}
int main()
{
test _a;
test* a=&_a;
if(a->foo)printf("OK");
else printf("ELSE");
a->foo=bar;
if(a->foo)printf("OK2");
else printf("ELSE2");
return 1;
}
The output i get when running is
ELSEOK2
The output is consistent with my expectations. I want know whether i can use
if(a->foo)
to check the situation, so that in future it will not lead to errors.
Also is it right to do curly braces { } in end of function pointer
void (*foo)(int a){};
without which i cannot check if foo->a is not zero.
void (*foo)(int a){}; does initialization to nullptr.
It is equivalent to
void (*foo)(int a) = nullptr;
and
if (a->foo) (or if (a->foo != nullptr)) is correct way to check is pointer is not nullptr.
If I create a class in c++, it is possible to call a function of an object of this class, even if this class does not exists.
For example:
Class:
class ExampleClass
{
private:
double m_data;
public:
void readSomeData(double param)
{
m_data = param;
}
}
Any function where this class is used:
int main()
{
ExampleClass* myClass;
myClass->readSomeData(2.5);
}
Ofcourse this wouldn't function, because myClass is not defined.
To avoid such situations, I check if ExampleClass objects are a null_ptr
example:
void readSomeData(double param)
{
if(this == null_ptr)
return;
m_data = param;
}
But gcc says:
'this' pointer cannot be null in well-defined C++ code; comparison may
be assumed to always avaluate to false.
Ofcourse that is only a warning, but I think it is not nice to have this warning. Is there a better way to check if the pointer of a class is defined?
Testing it in the class is the wrong way, the warning is correct about that if your code is well defined then this must not be null, so the test should happen at the time when you call the member function:
int main()
{
ExampleClass* myClass = nullptr; // always initialize a raw pointer to ensure
// that it does not point to a random address
// ....
if (myClass != nullptr) {
myClass->readSomeData(2.5);
}
return 0;
}
If a pointer must not be null at a certain part of your code then you should do it according to CppCoreGuideline: I.12: Declare a pointer that must not be null as not_null
Micorosoft provides an Guidelines Support Library that has an implementation for not_null.
Or if possible then don't use pointers at all but std::optional.
So a code setup could look like this:
#include <gsl/gsl>
struct ExampleClass {
void readSomeData(double ){}
};
// now it is clear that myClass must not and can not be null within work_with_class
// it still could hold an invalid pointe, but thats another problem
void work_with_class(gsl::not_null<ExampleClass*> myClass) {
myClass->readSomeData(2.5);
}
int main()
{
ExampleClass* myClass = nullptr; // always initialize a raw pointer to ensure
// that it does not point to a random address
// ....
work_with_class(myClass);
return 0;
}
The best way is not use pointers at all:
int main()
{
ExampleClass myClass;
myClass.readSomeData(2.5);
}
That way there's no need for any check, and in fact, checking this inside the function is moot.
If you need nullability, use std::optional instead.
Either don't use pointers as Bartek Banachewicz has pointed out, or properly initialize and check the pointer:
int main()
{
ExampleClass* myClass= 0;
if (myClass)
myClass->readSomeData(2.5);
return 0;
}
Of course you still have to add the instantiation of the object at some point, otherwise the code is nonsense.
Reverting this back to the original question. Going to post the more detailed question as a new question. Thanks everyone for the help and advice of avoiding the new. Having trouble passing around instances of objects in this question.
class dogClass {
public:
void setVariableA(std::vector<double> newNum) {
variableA.push_back(newNum);
}
dogClass &dogClass::operator=(const dogClass &src) {
variableA = src.variableA;
return *this;
}
private:
std::vector<std::vector<double>> variableA;
};
class animalClass {
public:
void getDogOne(dogClass &dogOne) {
dogOne = dogs[0];
}
void setDogOne(dogClass dogOne) {
dogs.push_back(dogOne);
}
private:
std::vector<dogClass> dogs;
};
int main() {
animalClass* iAnimalClass = new animalClass();
dogClass* iDogClassOne= new dogClass();
iAnimalClass->setDogOne(iDogClassOne);
std::vector<double> newNum;
newNum.push_back(12);
newNum.push_back(15);
iDogClassOne->setVariableA(newNum);
dogClass iDogClassTwo;
iAnimalClass->getDogOne(iDogClassTwo);
//Why are iDogClassOne and iDogClassTwo not equal.
return 0;
}
There are a couple of issues.
you don't have a copy constructor for your dog class as you have indicated in your title. what you have done is overloaded the = operator.
you are trying to pass iDogClassOne as pointer to the animalClass:: setDogOne() but animalclass::setDogOne receives the arguments by value, not as reference or pointer.
you can use the dereference operator*iDogClassOne. this pretty much telling the compiler you want to pass the object which the iDogClassOne is pointing at.
dogClass* iDogClassOne = new dogClass();
iAnimalClass->setDogOne(*iDogClassOne);
or a better way of doing, you can completly remove the heap allocation
dogClass dogobj;
iAnimalClass->setDogOne(dogobj);
same problem as described in (2). but this time your animalclass::getDogOne receives the arguments by a reference.this again can be easly fixed by modifying the getdogone or/and by passing a pointer. i will leave this as it is. if you still need a help let me know in comments and will edit it further. but i encourage you to try to give it a go first.
you are missing semicolon (;) at the end of class declarations
I had some code that looked something like the following:
struct fooclass {
char data[32];
}
fooclass makefoo() {
fooclass res;
// for example:
memset(res.data, 0, sizeof(res.data));
res.data[0] = 43;
return res;
}
struct do_stuff {
const fooclass& obj;
do_stuff(const fooclass& obj_in) : obj(obj_in) { }
void operate() { /* do things with obj; */ }
}
bool put_it_to_work(struct do_stuff& f) {
f.operate();
f.operate();
return true;
}
bool call_it_all() {
do_stuff local(makefoo());
return put_it_to_work(local);
}
With gcc, the code worked fine. With MSVC2012, local.obj became corrupted.
The question is: how long does the fooclass returned by makefoo last? Should it be until the end of call_it_all, or is it just until the end of the do_stuff local(makefoo()) line and I just got lucky? I'd appreciate a reference to the standard.
Here's your problem:
struct do_stuff {
const fooclass& obj;
obj is a reference, not a proper object, so no copy is ever made of the result of makefoo(). The real object that obj references is destructed when the local object has finished being constructed, specifically when the anonymous temporary variable that makefoo() returns is destroyed.
I think you were just lucky that it worked under gcc. Perhaps the object that obj refered to was being destroyed as it should be, only its data was left in RAM and the program appeared to work properly. Perhaps MSVC was "erased" the RAM that obj referred to such that attempts to use it would fail quickly.
I'm trying to make a chess program, but I want to be able to implement different AIs in it. Thus I made a abstract AIgeneric class and the derived class AIrandom off of AIgeneric. Then in my chessAI interface, I create a list of the the AIs, and try to call their getNextMove function and run into a segfault. The code is as below:
class AIgeneric {
public:
virtual int getNextMove(int*, const int &) = 0;
}
class AIrandom : public AIgeneric {
public:
AIrandom();
virtual int getNextMove(int*, const int &);
}
class chessAI {
public:
chessAI();
~chessAI();
void setAI();
int getNextMove(int*, const int &);
private:
vector<AIgeneric*> AIlist;
vector<string> names;
int selectedAI;
};
chessAI::chessAI () {
AIrandom randomAI;
AIlist.push_back(&randomAI);
names.push_back("Random AI");
selectedAI = -1;
}
int chessAI::getNextMove(int * board, const int & color) {
return AIlist[selectedAI]->getNextMove(board, color); //segfault on this line
}
It'd be great if anyone could help me on this problem!
Edit: I do set selectedAI to 0 before calling getNextMove.
In this code:
chessAI::chessAI () {
AIrandom randomAI;
AIlist.push_back(&randomAI);
names.push_back("Random AI");
selectedAI = -1;
}
You store a pointer to a local variable into your vector. After the constructor returns that pointer is no longer valid.
Remember that all local variables are stored on the stack, and the stack is reused in other functions. So when you use the pointer in the vector, it now points to some other functions memory and not the one object you declared.
This can be solved in three ways:
Allocate the object on the heap:
AIlist.push_back(new AIRandom);
Not using pointers at all.
Use smart pointers, such as std::unique_ptr.
You call selectedAI = -1; and then AIlist[selectedAI]->.... What do you expect AIlist[-1] to be, other than undefined behavior?
I expect this is because AIlist[selectedAI] is out of bounds. You can confirm this by replacing it with AIlist.at(selectedAI). Keep in mind that this index is -1 immediately after the constructor...