Why is the vptr discarded when I copy objects? [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Example
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <iomanip>
struct father
{
int variable;
father(){variable=0xEEEEEEEE;};
virtual void sing(){printf("trollolo,%x\n",variable);}
~father(){};
};
struct son:father
{
son(){variable=0xDDDDDDDD;};
virtual void sing(){printf("trillili,%x\n",variable);}
~son(){};
};
int main()
{
father * ifather=new(father);
son * ison=new(son);
father uncle;
father * iteachers;
*((long long*)&uncle)=0xDEAF;
iteachers=(father*)malloc(20*sizeof(father));
//ineffective assignments
iteachers[0]=*ifather;
uncle=*ifather;
ifather->sing();//called to prevent optimization
ison->sing();//only to prevent optimization
std::cout.setf(std::ios::hex);
std::cout<<"father:"<<*((long long*)ifather)<<","<<std::endl;
std::cout<<"teacher0:"<<*((long long*)&(iteachers[0]))<<","<<std::endl;
std::cout<<"uncle:"<<*((long long*)&uncle)<<","<<std::endl;
std::cout<<"(son:"<<*((long long*)ison)<<"),"<<std::endl;
// uncle.sing();//would crash
}
The vtable pointer of teachers[0] is zero when compiled with gcc.
Also the vtable pointer of uncle keeps its original value instead of being overwritten.
My questions: Why HAS it be that way?
Is there a CLEAN workaround? Can i go with uncle._vptr=ifather->_vptr and still be portable? What is the ORDINARY routine to copy an object? Should I even file a bug?
Note: it should copy the whole object platform-independant, because no matter how the identification of the object type is done, since it should always be inside the object's data block!
The article
Why does my C++ object loses its VPTr
didn't help me, that must have a different reason.

As I understand it, basically the question is whether this code:
#include <iostream>
using namespace std;
struct Base
{
virtual void sing() { cout << "Base!" << endl; }
virtual ~Base() {}
};
struct Derived: Base
{
void sing() override { cout << "Derived!" << endl; }
};
auto main()
-> int
{
Base* p = new Derived();
*p = Base();
p->sing(); // Reporting "Base" or "Derived"?
}
should report "Base" or "Derived".
In short, assignment does not change the type of an object.
Hence, it reports "Derived".

Related

Is static_cast creating new child object? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
This code runs fine, when it should have a run-time error, since i haven't instantiated a derived class object.
#include <iostream>
using namespace std;
class Person {
public:
void walk() { cout << "person walking" << endl; }
};
class Employee :public Person {
public:
void work() { cout << "employee working" << endl; }
};
void main() {
Person* p = new Person();
Employee* e = static_cast<Employee*>(p);
e->work();// this is working - but why? it should fail at runtime
}
If static_cast only casting the pointer, how is it possible to call a child member function?
At what point is the child instantiated?
Is static_cast also instantiating objects?
No.
Your assertion that your code should "crash at runtime" is, unfortunately, wrong. Your code exhibits undefined behaviour meaning that it could do literally anything. In this case I expect it works because the address of the function is the same in both objects but really, it could be for any reason.

c++ forward declaration + ifndef also needs pointers [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Array:
#ifndef ARRAY_H
#define ARRAY_H
#include <bits/stdc++.h>
using namespace std;
namespace Maifee{
class Value;
class Array {
public:
Array();
vector<Value> _elements;
};
}
#endif // ARRAY_H
Object :
#ifndef OBJECT_H
#define OBJECT_H
#include <bits/stdc++.h>
#include "value.h"
using namespace std;
namespace Maifee{
class Value;
class Object{
public:
Object();
map<string, Value> _members;
};
}
#endif // OBJECT_H
Value :
#ifndef VALUE_H
#define VALUE_H
#include <bits/stdc++.h>
#include "array.h"
#include "object.h"
using namespace std;
namespace Maifee{
class Array;
class Object;
class Value {
public:
Value();
Value(Object *__object);
Array *_array;
Object *_object;
};
}
#endif // VALUE_H
I'm learning C++ at my best. With my teeny tiny knowledge in C++, I am trying to write some code. First reason I'm moving C++, pointers take a lot's of time.
Here I'm writing these code, where forward-declaration is necessary, and due to this even after using forward-declaration and ifndef, I need to use pointer, which I really don't want.
Can anyone really help me with this, how can I remove circular dependency??
Do I need to go back to C?
When using pointer I faced many problems such as, I have just one key-value pair in my map, but in the next line size becomes a very large number, out of nowhere.
Code inside main :
Object object=Object();
cout << "pop obj tem len" << object._members.size() << endl; //gives 0 as expected
object._members = members;
cout << "pop obj tem len" << object._members.size() << endl; //gives the expected number
Value val=Value(&object);
cout << val._object->_members.size() << "size here" << endl; //gives a random number
Constructor for Value with Object parameter :
Value::Value(Object *__object)
{
Object object;
object._members.insert(__object->_members.begin(), __object->_members.end());
_object = &object;
}
You can't avoid the forward-declarations and pointers in this situation.
class Object has a map<string, Value> member, and class Array has a vector<Value> member. Which means Value must be a fully-defined, complete type by the time Object and Array are being compiled, as map and vector need to know the total size of their element types. If Value were to have non-pointer Array and Object members, then Object and Array would need Value to be a complete type, but Value would need Object and Array to be complete types. Catch-22!
So, you have to use forward declarations and pointers/references for the Value members in order to make this kind of circular referencing work properly, since pointers/references to incomplete types are allowed.
UPDATE: In your Value constructor that takes an Object* parameter, you are setting the _object member to point at a local Object instance that goes out of scope and is destroyed when the constructor exits, thus leaving _object dangling. That is why the subsequent val._object->_members.size() expression in main() produces garbage (you are lucky the code didn't crash outright) - val._object is pointing at invalid memory, so its members is not a valid map object and so reading its size() is undefined behavior. That goes right back to the original comment I posted:
You are likely accessing an invalid pointer.
To solve this, depending on your actual design goal, the Value constructor needs to either:
construct a new Object dynamically, which will have to be delete'd later. You will also have to provide a proper copy constructor and copy assignment operator:
Value::Value()
{
_object = NULL;
_array = NULL;
}
Value::Value(Object *__object)
{
_object = new Object;
_array = NULL;
if (__object)
_object._members = __object->_members;
}
Value::Value(const Value &__value)
{
_object = new Object;
_array = NULL;
if (__value._object)
_object._members = __value._object->_members;
}
Value::~Value()
{
delete _object;
}
Value& Value::operator=(const Value &__value)
{
if (&__value != this)
{
Value tmp(__value);
std::swap(_object, tmp._object);
std::swap(_array, tmp._array);
}
return *this;
}
simply store the Object* pointer it is given:
Value::Value(Object *__object)
{
_object = __object;
_array = NULL;
}

This member function is not getting called, and I can't figure out how to rectify it [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I'm reading through my C++ textbook for an upcoming class, and following along an exercise in the book. This exercise compiles and seems to give the results that you would expect, but it seems there is an error though, and I can't figure out how to fix it.
Here is the code.
// Page 706 from text
//Contents of ThisExample.h
class Example
{
int x;
public:
Example(int a){x=a;}
void setValue(int);
void printAddressAndValue();
};
/*
//Contents of ThisExample.cpp
#include "ThisExample.h"
*/
#include <iostream>
using namespace std;
/*********************************************************
* Set value of object.
*********************************************************/
void Example::setValue(int a) // <---------- Doesn't execute
{ // <---------- Doesn't execute
x = a; // <---------- Doesn't execute
} // <---------- Doesn't execute
void Example::printAddressAndValue()
{
cout<< "The object at address " << this << " has "
<< "value "<< (*this).x<<endl;
}
/*
//Contents of main program
#include <iostream>
#include "ThisExample.h"
using namespace std;
*/
int main()
{
Example ob1(10), ob2(20);
// Print the addresses of the two objects
cout<<"Addresses of objects are "<< &ob1 << " and "<<&ob2<<endl;
// Print the addresses and values from within the member function
ob1.printAddressAndValue();
ob2.printAddressAndValue();
return 0;
}
In the book, they talk about replacing
void Example::setValue(int a)
{
x = a;
}
with
void Example::setValue(int a)
{
this->x = x;
}
But when I step through it with a debugger (which I am also new to), I don't see that function ever getting called.
I've tried commenting out the function entirely and it still runs, that's how I know it isn't getting called.
I also tried removing from the class
Example(int a){x=a;}
but then it doesn't compile. Any help? I just want to move along with the textbook, which is called "Starting Out With C++ Early Objects
Judy Walters, Godfrey Muganda, Tony Gaddis" and the exercise is on page 706.
Thanks
It doesn't ever get called, because you never call it.
The only place that the member variable x is set, in this particular example, is in the constructor. And the constructor happens to do so directly, rather than by calling setValue().
You could later call setValue() to change x, but currently you do not.
It's not uncommon to provide functionality that makes sense to be part of the class, even if you're not using that functionality quite yet. Although, unless you're writing a library, you generally wouldn't do too much of writing functionality you don't yet need.
Perhaps later exercises in the textbook involve calling setValue(). I would just continue reading and not worry about this.

Adding subClasses to BaseClass vector C++ doesn't work [closed]

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 4 years ago.
Improve this question
i have the following problem, i have 2 Classes FooClass and BaseClass, and multiple SubClasses of BaseClass.
I want to add these various Subclasses into the same Vector in FooClass, because i am just implementing functions from baseclass, so i can access them through the vector key.
In the following example, each subclass sets the string name of the BaseClass with setName(), and returns it with getName().
Every subclass uses also thisFunctionisforAll() defined in the BaseClass.
The code does compile fine, except if i add vClasses.push_back(thesubclass);
So i need help how i can put all these subclasses of BaseClass into the same vector.
I want to iterate through the varius subClasses of BaseClass in the FooClass vector to output their names.
Example is in main.cpp
I thought i can add different subclasses to a vector if i they share the baseclass and the vector is type of the baseclass.
Here is the source:
FooClass.h:
#ifndef TESTPROJECT_FOOCLASS_H
#define TESTPROJECT_FOOCLASS_H
#include <vector>
#include "BaseClass.h"
using namespace std;
class FooClass
{
private:
vector<BaseClass> vClasses;
public:
void addClassToVector(BaseClass &classToAdd);
void getNames();
};
#endif //TESTPROJECT_FOOCLASS_H
FooClass.cpp
#include "FooClass.h"
void FooClass::addClassToVector(BaseClass &thesubclass)
{
vClasses.push_back(thesubclass);
}
void FooClass::getNames()
{
for (size_t i; i < vClasses.size(); i++)
{
cout << vClasses[i].getName() << endl;
}
}
BaseClass.h
#ifndef TESTPROJECT_BASECLASS_H
#define TESTPROJECT_BASECLASS_H
#include <iostream>
using namespace std;
class BaseClass
{
protected:
string name;
public:
virtual void setName()= 0;
virtual string getName()=0;
void thisFunctionisforAll();
};
#endif //TESTPROJECT_BASECLASS_H
BaseClass.cpp
#include "BaseClass.h"
void BaseClass::thisFunctionisforAll() {
cout << "Every subclass uses me without implementing me" << endl;
}
SubClass.h
#ifndef TESTPROJECT_SUBCLASS_H
#define TESTPROJECT_SUBCLASS_H
#include "BaseClass.h"
class SubClass : public BaseClass {
virtual void setName();
virtual string getName();
};
#endif //TESTPROJECT_SUBCLASS_H
SubClass.cpp
#include "SubClass.h"
void SubClass::setName()
{
BaseClass::name = "Class1";
}
string SubClass::getName() {
return BaseClass::name;
}
SubClass2.h
#ifndef TESTPROJECT_SUBCLASS2_H
#define TESTPROJECT_SUBCLASS2_H
#include "BaseClass.h"
class SubClass2 : public BaseClass
{
virtual void setName();
virtual string getName();
};
#endif //TESTPROJECT_SUBCLASS2_H
SubClass2.cpp
#include "SubClass2.h"
void SubClass2::setName()
{
BaseClass::name = "Class 2";
}
string SubClass2::getName() {
return BaseClass::name;
}
main.cpp
#include "FooClass.h"
void FooClass::addClassToVector(BaseClass &thesubclass)
{
vClasses.push_back(thesubclass);
}
void FooClass::getNames()
{
for (size_t i; i < vClasses.size(); i++)
{
cout << vClasses[i].getName() << endl;
}
}
I think the solution will be simple, but i am experienced in PHP and there i hadn't such issues.
You need to use pointers or references. Polymorphism only works in C++ when you're using pointers. You cannot treat a subclass as a superclass unless you're using pointers or references. You'd need std::vector<BaseClass*> to be able to have a container of both the base class and subclass.
Since you're new to the language, I would recommend researching how pointers work.
Containers like vectors contain things directly, not references to things (as found in, e.g., Java - not sure about PHP). If you've got a class Foo then a std::vector<Foo> will contain Foo instances. If there's a class Bar that derives from Foo and you put a Bar into this vector you'll only get the Foo part of it. The rest is cut off, or sliced, as described here: C++ - What is object slicing?. This is the way it works in C++.
Now, you can put pointers into the vector, e.g., a vector<Foo*>. But the vector object won't own the things pointed to (as it would in a language like Java, for example). It'll just be holding pointers. So you have to manage object lifetime separately. This is a main feature of C++. If you want the vector to own the objects you've got to put your pointers in there as a specific type of wrapped pointer, usually std::unique_ptr or std::shared_ptr.
But now you're getting into more complex but absolutely fundamental C++ stuff and you'll need to understand a lot about how ownership and containers work. Still, there are plenty of ways to learn that, I'm sure you know, and Stack Overflow's c++ tag will have a lot of questions on those topics with useful answers for you.

Use a struct from a object? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I started with working code (not written by me obviously), I saw them make a class object dataflash which made sense to me, but then after that they used:
DataFlash::ID id;
Which is obviously because they needed an object of that struct, but the fact they went back to the DataFlash class bugged me, not sure why, but I thought "No, no, you should be using the object we just made now" and promptly changed it to what I have below, which produces the following error:
error: invalid use of ‘struct main()::DataFlash::ID’
Well that's no fair, I'm basically doing the same thing to my eye, why is this invalid use? Are structs (and nested classes I assume too) useless once they are in an object?
#include <iostream>
using namespace std;
int main()
{
class DataFlash
{
public:
struct ID
{
uint8_t manufacturer; /**< Manufacturer id **/
uint8_t device[2]; /**< Device id **/
uint8_t extendedInfoLength; /**< Extended device information**/
};
};
DataFlash dataflash;
dataflash.ID id;
return 0;
}
The code defines several layers of nested scope, the original code is doing scope resolution with the scope resolution operator ::
Your example uses a member access operator . and the struct ID simply is not a member, it lives in the scope of your type, a type and value is not the same thing.
As a footnote, enumerations can be accessed in both ways due to enum's scoping rules.
#include <iostream>
struct object {
enum identifier {
a = 2,
b = 16,
};
identifier id;
};
int main(int argc, char* argv[]) {
object obj;
std::cout << object::a << std::endl;
std::cout << obj.b << std::endl;
}