The following code produces different result in VS 2013 Release/Debug [duplicate] - c++

This question already has answers here:
Do distinct functions have distinct addresses?
(4 answers)
Closed 7 years ago.
is this a bug in VS 2013 compiler?
The following code produces different result in debug and release.
In debug the result is as expected, but in release it is "A"
#include <cstdio>
struct A
{
virtual void* getClass() { return A::ID; };
static void ID(){};
};
struct B : public A
{
virtual void* getClass() { return B::ID; };
static void ID(){};
};
struct C : public A
{
virtual void* getClass() { return C::ID; };
static void ID(){};
};
int main(int argc, char *argv[])
{
A* d = new C;
if (d->getClass() == A::ID)
{
printf("A");
}
else if (d->getClass() == B::ID)
{
printf("B");
}
else if (d->getClass() == C::ID)
{
printf("C");
}
}

It's due to compiler optimizations.
It appears that whether the compiler should perform this kind of optimization is debatable Do distinct functions have distinct addresses? .
typeid
A more conventional way is to use typeid to verify the runtime types. Note you dereference the pointer to get the type of the derived class.
if (typeid(*d) == typeid(A))
{
printf("A");
}
else if (typeid(*d) == typeid(B))
{
printf("B");
}
else if (typeid(*d) == typeid(C))
{
printf("C");
}
Disable Optimization
However, because /OPT:ICF can merge identical data or functions, it can change the function names that appear in stack traces.
You can use /OPT:NOICF in release to prevent the behavior.
Also, you can see that actually implementing the functions differently causes it to work as you expect.
Example Code
#include <string>
struct A
{
virtual std::string getClass() { return A::ID(); }
static std::string ID(){ return "A"; }
};
struct B : public A
{
virtual std::string getClass() { return B::ID(); }
static std::string ID(){ return "B"; }
};
struct C : public A
{
virtual std::string getClass() { return C::ID(); }
static std::string ID(){ return "C"; }
};
int main(int argc, char *argv[])
{
A* d = new C;
if (d->getClass() == A::ID())
{
printf("A");
}
else if (d->getClass() == B::ID())
{
printf("B");
}
else if (d->getClass() == C::ID())
{
printf("C");
}
}

Related

How to make a generic template C++ pointer?

Assume the snippet below. How can I make this compiling/working? I do not want to move print to the String/Float class, because in my real world situation this function is combining a lot of data.
So basically I want a pointer/member to "any type (in this case string/float)" then use it, and call dynamically something else (in this case print)?
I assume that this does not work (among others) because it cannot determine at compile time which type T of ptr will have at compile time.
What is the general pattern to solve such kind of problems?
#include <iostream>
template<typename T>
class AbstractClass {
virtual T getValue()=0;
};
class StringClass : public AbstractClass<std::string> {
std::string getValue() override {
return "A";
}
};
class FloatClass : public AbstractClass<float> {
float getValue() override {
return 1;
}
};
class Processor {
public:
AbstractClass<T>* ptr;
void doIt() {
ptr=new StringClass();
print(ptr->getValue());
delete ptr;
ptr=new FloatClass();
print(ptr->getValue());
delete ptr;
}
void print(std::string i) {
std::cout << "String "<<i<<std::endl;
}
void print(float i) {
std::cout << "Float "<<i<<std::endl;
}
}
int main() {
Processor a;
a.doIt();
}
If you want an object that's 'one of' a given set of types, you can use std::variant<Ts...>. Mathematically, it represents discriminated/tagged union. This way, you don't need a pointer, neither a base class. Example:
#include <iostream>
#include <variant>
class StringClass {
std::string getValue() override {
return "A";
}
};
class FloatClass {
float getValue() override {
return 1;
}
};
using ClassWithGetValue = std::variant<StringClass, FloatClass>;
class Processor {
public:
ClassWithGetValue v;
void doIt() {
v = StringClass();
std::visit([&](auto&& v1) {
print(v1.getValue());
});
v = FloatClass();
std::visit([&](auto&& v1) {
print(v1.getValue());
});
}
void print(std::string i) {
std::cout << "String "<<i<<std::endl;
}
void print(float i) {
std::cout << "Float "<<i<<std::endl;
}
}
int main() {
Processor a;
a.doIt();
}

Issue with polymorphism with smart pointers and vectors c++

I am currently trying to learn c++ and I am having an issue when trying to create a vector which iterates through several different objects whom all inherit from the same base class with smart pointers.
I parse a file and create the objects and insert them into the vector depending on the character parsed but I keep getting the error:
Error C2664 'std::unique_ptr<Test *,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': cannot convert argument 1 from 'std::unique_ptr<Test2,std::default_delete<_Ty>>' to 'std::nullptr_t'"
Code is as follows:
class Test {
public:
virtual ~Test(){}
virtual int update() {}
};
class Test2 : public Test {
private:
int a;
public:
Test2() {
}
Test2(int n) {
a = n;
}
int update() override {
return a;
}
};
class Test3 : public Test {
private:
int a;
public:
Test3() {
}
Test3(int n) {
a = n;
}
int update() override {
return a;
}
};
class Test4 : public Test {
private:
int a;
public:
Test4() {
}
Test4(int n) {
a = n;
}
int update() override {
return a;
}
};
class manager {
private:
std::vector<std::unique_ptr<Test*>> vList;
std::ifstream lvlFile;
public:
std::string tmp;
manager() {
}
~manager() {
}
void init(const char *path) {
lvlFile.open(path, 0);
while (lvlFile.eof() != true) {
std::getline(lvlFile, tmp);
for (char& a : tmp) {
switch (a) {
case 'w':
vList.emplace_back(std::make_unique<Test2>(2));
break;
case 'g':
vList.emplace_back(std::make_unique<Test3>(3));
break;
}
}
}
}
void print() {
for (auto& i : vList) {
std::cout << (*i)->update() << std::endl;
}
}
};
manager *m;
int main() {
m = new manager();
m->init("lvl.txt");
_getch();
}
Maybe I have misunderstood something crucial here but I have been looking around and found no real answers so any pointers to this would be most welcome!
Change std::vector<std::unique_ptr<Test*>> to std::vector<std::unique_ptr<Test>>.
std::unique_ptr<Test*> is a pointer to pointer (Test**).

Obtain variable from derived class c++

I'm looking to do something only if the class is a specific derived class. That is I have:
class X{
int id;
}
class A: public X{
void run();
}
class B: public X{
int lala;
}
And I want to do something along the line of:
main(){
vector<X *> types;
types.push_back(new A);
types.push_back(new B);
int var = 0;
for(int i = 0; i<types.size(); i++){
if(types[i].isType(A)) {types[i].run();}
}
for(int i = 0; i<types.size(); i++){
if(types[i].isType(B)) {var = lala;}
}
}
I do not want class B to have anything equivalent to run(), nor do I want class A to have an equivalent to lala.
I know fortran has a workaround with
select type ( x => var )
class is ( A )
x.run()
end select
But I wasn't sure what my options in C++ were.
Thanks
You are looking for dynamic_cast.
#include <vector>
using namespace std;
class X {
public:
int id;
virtual ~X() = default;
};
class A : public X {
public:
void run() {}
};
class B : public X {
public:
int lala;
};
main(){
vector<X *> types;
types.push_back(new A);
types.push_back(new B);
int var = 0;
for(int i = 0; i<types.size(); i++){
if (auto ta = dynamic_cast<A *>(types[i])) {
ta->run();
}
}
for(int i = 0; i<types.size(); i++){
if (auto tb = dynamic_cast<B *>(types[i])) {
var = tb->lala;
}
}
}
Also see it in action here: https://onlinegdb.com/B1d29P5if.
I had to fix a few other problems with the code. Since they are not a part of your question, I won't clarify here, but you are welcome to ask if something is not clear.
EDIT: The above solution has memory leaks, which I didn't fix, as it wasn't required by the question. For completeness, here is the main function with memory leaks fixed (https://onlinegdb.com/ByeOmu9iz):
int main() {
vector<unique_ptr<X>> types;
types.emplace_back(new A);
types.emplace_back(new B);
int var = 0;
for(int i = 0; i < types.size(); ++i) {
if (auto ta = dynamic_cast<A *>(types[i].get())) {
ta->run();
}
}
for(int i = 0; i < types.size(); ++i) {
if (auto tb = dynamic_cast<B *>(types[i].get())) {
var = tb->lala;
}
}
}
Note that this is a C++11 solution.
If you're working with an even older compiler, you'll have to keep using plain pointers as in the original solution, and deallocate the memory manually at the end by calling delete on each element of the vector. (And hope nothing throws an exception before you reach that step.)
You'll also have to replace auto ta with A* ta and auto tb with B* tb.
A modern C++17 solution to this problem is to use a vector of variants, i.e. std::vector<std::variant<A, B>>. You need a modern compiler for this.
Here is a complete example, based on the std::variant documentation:
#include <vector>
#include <variant>
#include <iostream>
class X {
int id;
};
class A: public X {
public:
void run() {
std::cout << "run\n"; // just for demonstration purposes
}
};
class B: public X {
public:
B(int lala) : lala(lala) {} // just for demonstration purposes
int lala;
};
int main() {
std::vector<std::variant<A, B>> types;
types.push_back(A()); // no more new!
types.push_back(B(123)); // no more new!
int var = 0;
for (auto&& type : types) {
std::visit([&](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, A>) {
arg.run();
} else {
var = arg.lala;
}
}, type);
}
std::cout << var << '\n'; // just for demonstration purposes
}
As a nice bonus, this solution elegantly gets rid of dynamic allocation (no more memory leaks, no smart pointers necessary).
I have two ideas....
Why not have a shared method that returns a value that gives context as to whether or not it is an A or B? If for example, lala is expected to return only values 0 or greater, you could have void run() instead be int run() and return -1 at all times.
class X {
int id;
virtual int run() = 0; //Assuming X isn't meant to be instantiated
}
class A: public X {
// Return -1 to differentiate between As and Bs
int run() { return -1; }
}
class B: public X {
int lala;
int run() { return lala;}
}
Then you have...
main(){
vector<X *> types;
types.push_back(new A);
types.push_back(new B);
int var = 0, temp = 0;
for( int i = 0; i<types.size(); i++ ) {
if( (temp = types[i].run()) != -1 )
var = temp;
....
}
}
Again, only works if lala would never expect to return a particular range of values.
You could also hide information in X, upon creation of an A or B to keep track of what you have.
class X {
int id;
bool isA;
}
class A: public X {
A() : isA(true) { };
void run();
}
class B: public X {
B() : isA(false) { } ;
int lala;
}
Then you have...
main(){
vector<X *> types;
types.push_back(new A);
types.push_back(new B);
int var = 0;
for( int i = 0; i<types.size(); i++ ) {
if( types[i].isA == true ) {
types[i].run();
}
else {
var = types[i].lala;
}
}
Naturally if you expect to add C, D, E, .... it will no longer be worth it, but for only two derived classes it isn't all that bad.
I would justify this based on the fact that users are already going to have to peer into the derived classes to see why they behave so differently for being derived from the same class. I would actually look into whether or not it makes sense for A and B to derive from X based on their interface.
I also wouldn't recommend dynamic_cast(ing) without informing someone that it's one of the more dangerous casts to perform and typically not recommended.
You could use dynamic_cast to check if the base class pointer is convertible to a derived instance.
Another option would be to have a virtual function that returns the typeinfo of the class and thus use that information to cast the pointer to a convertible type. Depending on how dynamic_cast is implemented this could be more performant. Thus, you could use this if you want to try and see whether or not this method is quicker on your platform.
As #Jarod42 noted, you would need to have a virtual function, destructor in this case, for dynamic_cast to work. In addition, you would simply need a virtual destrctor to avoid undefined behavior when deleting the instance.
Example
#include <iostream>
#include <string>
#include <vector>
#include <typeinfo>
struct A {
virtual ~A() {
}
virtual const std::type_info& getTypeInfo() const {
return typeid(A);
}
};
struct B : public A {
virtual const std::type_info& getTypeInfo() const override {
return typeid(B);
}
};
struct C : public A {
virtual const std::type_info& getTypeInfo() const override {
return typeid(C);
}
};
int main()
{
std::vector<A*> data;
data.push_back(new A);
data.push_back(new B);
data.push_back(new C);
for (auto& val : data) {
if (val->getTypeInfo() == typeid(A)) {
std::cout << "A";
}
else if (val->getTypeInfo() == typeid(B)) {
std::cout << "B";
}
else if (val->getTypeInfo() == typeid(C)) {
std::cout << "C";
}
std::cout << std::endl;
}
for (auto& val : data) {
delete val;
}
}

default value of const reference parameter

Currently I have two functions:
void foo(const A & a) {
...
result = ...
result += handle(a); // 1
bar(result);
}
void foo() {
...
result = ...
bar(result);
}
All code in foo() are the same except 1.
Can I merge them to one function like following?
void foo(const A & a = 0) {
...
...
if (a) result += handle(a); // this won't work, but can I do something similar?
bar(result);
}
Btw, the parameter has to be a reference as I would like to keep the interface unchanged.
You can use the Null Object Pattern.
namespace
{
const A NULL_A; // (possibly "extern")
}
void foo(const A & a = NULL_A) {
...
result = ...
if (&a != &NULL_A) result += handle(a);
bar(result);
}
No. A reference is always an alias for a real object (assuming you don't trigger undefined behavior). You can achieve similar behavior without code duplication by accepting a pointer instead:
void foo_impl(A const* obj) {
// code as before, except access obj with -> rather than .
}
void foo (A const& obj) {
foo_impl(&obj);
}
void foo() {
foo_impl(nullptr);
}
In the spirit of DRY, why not merge them as such?
void foo(const A & a) {
foo();
handle(a);
}
void foo() {
...
...
}
The entire idea of using reference is that you avoid the NULL pointer issue. The reference nothing but an alias for the real object. I have an another simple idea for your program, basically you want to achieve two functionality with same function - using default parameters. Here is the code. Please excuse me for the variable names.
class ABC
{
public:
int t;
ABC operator=(ABC& other)
{
other.t = 0;
}
};
ABC other;
void foo( ABC &a=other);
void foo( ABC &a)
{
if( a.t == 0)
qDebug()<<"The A WAS ZERO";
else
qDebug()<<"THE A isn't zero";
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
ABC hello;
hello.t = 100;
foo();
foo(hello);
return a.exec();
}
Here is the output.
The A WAS ZERO
THE A isn't zero
Use a base class that provides an interface, and two derived classes that implement the interface, one using A and the other using nothing.
Refactor foo to use a common foo.
struct Handler
{
virtual int get() = 0;
};
struct AHandler : Handler
{
AHandler(const A& a) : a_(a) {}
virtual int get() { return handle(a_); }
const A& a_;
}
struct NullHandler : Handler
{
virtual int get() { return 0; }
}
void foo(const Handler & h) {
...
result = ...
result += h.get();
bar(result);
}
void foo(const A & a) {
AHandler ah(a);
foo(ah);
}
void foo() {
NullHandler nh(a);
foo(nh);
}

how to do function pointer like in C++, but for variable

sorry for the title, it's quite confusing to explain, but it will be more clear with example
In C, I used to write program like this :
void createClassA()
{
}
void createClassB()
{
}
typedef struct {
const char *name;
void (*create_class)();
} MapList;
MapList mapList[] = {
{"A", &createClassA},
{"B", &createClassB },
};
void create(const char *name)
{
int i=0;
for (i=0; i < sizeof(mapList) / sizeof(MapList); i++) {
if (strcmp(name, mapList[i].name) == 0) mapList[i].create_class();
}
}
int main(int argc, char** argv)
{
if (argc < 1) return -1;
create(argv[1]);
return 0;
}
So if I have more types, all I have to do is to create the function itself and add it to the mapList.
but in C++, the best I can do is something like:
#include <iostream>
class myA{};
class myB{};
class myC{};
class Base
{
public:
template<class T>
void createClass()
{
T* t = new T();
//t->doSomethingUseful();
}
void create(const std::string name)
{
if (name=="A") createClass<myA>();
else if (name=="B") createClass<myB>();
else if (name=="C") createClass<myC>();
}
};
int main(int agrc, char** argv)
{
if (argc<1) return -1;
Base b;
b.create(argv[0]);
return 0;
}
Can I create something like :
typedef struct {
std::string name;
[CLASS_TYPE] class_type; <== I don't know how
} MapList;
so I can create a mapping List but fill it with class Type, something like
mapList[] = {
{"A", myA},
{"B", myB},
{"B", myC},
};
and then I can create iteration like:
for (int i=0; i<sizeof(mapList) / sizeof(MapList); i++) {
if (mapList[i].name == name) b.createClass<mapList[i].classType>();
}
Thanks guys :)
In C++ you can use std::function in the <functional> standard header. Specifically, your example for the map list can be written as (with lambdas):
std::map<std::string, std::function<void()>> mapList;
mapList["A"] = []() { /* ... */ };
mapList["B"] = []() { /* ... */ };
or just (without lambdas):
void createClassA() {}
void createClassB() {}
std::map<std::string, std::function<void()>> mapList;
mapList["A"] = createClassA;
mapList["B"] = createClassB;
In C++ you could do that with virtual functions:
struct ClassMaker {
virtual void create_class() = 0;
};
struct ClassMakerA : public ClassMaker {
virtual void create_class() {
...
}
};
struct ClassMakerB : public ClassMaker {
virtual void create_class() {
...
}
};
Now you can create a std::map<std::string,ClassMaker*> with your "factories", like this:
ClassMakerA makerA;
ClassMakerB makerB;
// This syntax requires C++11
std::map<std::string,ClassMaker*> makers = {
{"A", &makerA}
, {"B", &makerB}
};
Finally, you can now call create_class() based on a std::string value, like this:
void create(const std::string &name) {
ClassMaker *maker = makers[name];
if (maker) maker -> create_class();
}
You could look for Boost::any, which provides "a variant value type".
You can use derived classes and object factory, something like that would work. You can improve it by make create method to return smart pointers and make A and B constructors private to avoid creating objects on the stack.
class Base
{
static Base* create(const char *name);
};
class A : public Base
{
};
class B : public Base
{
};
Base* Base::create(const char *name)
{
if(strcmp(name,"A")==0)
return new A();
if(strcmp(name,"B")==0)
return new B();
return 0;
}
int main(int agrc, char** argv)
{
if (argc<1) return -1;
Base *b = Base::create(argv[0]);
return 0;
}
It is somewhat similar to solution by #dasblinkenlight, but avoid virtual functions overhead.