This question already has answers here:
Accessing class members on a NULL pointer
(8 answers)
Closed 9 years ago.
Why is it possible to use class member functions on an uninitialized object (at least I believe it's uninitialized). The following runs without error:
// A.h
class A {
public:
explicit A(int n) : n_(n) {};
~A() {};
int foo() {
return n_;
};
int bar(int i) {
return i;
};
private:
int n_;
};
with
// main.cc
#include <iostream>
#include "A.h"
int main(int argc, char **argv) {
A *myClass;
std::cout << myClass->bar(5) << "\n";
}
Now, certainly attempting myClass->foo();fails, but why can we even use bar() when all we've declared is that a pointer to A exists, and is called myClass? Is this acceptable coding style/is there ever a reason to use this approach?
why can we even use bar() when all we've declared is that a pointer to A exists, and is called myClass?
Because, in general, it's impossible for the compiler to tell whether a pointer will be valid at runtime; so it isn't required to diagnose this error. However, in this case, a decent compiler should be able to issue a warning, as long as you're not building with warnings disabled.
Is this acceptable coding style/is there ever a reason to use this approach?
Absolutely not. Dereferencing an invalid pointer gives undefined behaviour.
Because you can't know if the block of memory where myClass is pointing to is an initialized object, it have right syntax, but undefined behavior, however if want to prevent, you should use -Wall or a similar compiler option (depends on your compiler) and it will warn you about the uninitialized pointer.
Related
This question already has an answer here:
Why can in-class initializers only use = or {}? [duplicate]
(1 answer)
Closed 5 years ago.
I'm just going through the basic OOP concepts in C++ and came across the following:
class A{
public:
int i(20); //line 1
};
int main()
{
int j(20);
cout<<j<<endl;
A obj;
cout<<obj.i<<endl;
}
I get the following error at line1 when compiling (tried in both gcc and MSVC++),
expected identifier before numeric constant
I know how to assign default value for a non-static member (which can be done from C++11 on wards in different ways), but I couldn't get the reason why only this kind of default value initialization is not possible as doing the same initialization (for normal variables) anywhere else is valid.
What could be the reason for such restriction?
Edited:
From the links and answer provided, it is because "it might read as function declaration in some cases. Because of this ambiguity, it is not allowed."
But consider the following case:
//global scope
struct B{
int j;
};
int B = 10;
int object(B);
This is also a similar case, where int object(B) might be understood as a function object taking B object as argument and with int return type.
I tried this in gcc and MSVC++ and object is treated as an int variable. Why it is not restricted in this case?
Using parentheses was deemed to be too confusing since it would read very similarly to a function declaration. Think about the case of a default constructor:
class A{
public:
int i(); // function declaration -- did you mean to
// use the default constructor instead?
};
There are other ways to do it though:
class A{
public:
int i = 20;
int i{20};
int i = {20};
};
This question already has answers here:
Which is the difference between declaring a constructor private and =delete?
(7 answers)
Closed 7 years ago.
Let us assume we have a class X and we want wo explicitly forbid, let say the standard constructor. I used for a long time in the Header file:
private:
X(); // 1.
so, that the contructor was disabled outside the class, so for anybody. But recently I have learned that in C++11 follwoing was recommended:
X() = delete; // 2.
Both would achive my wish to forbid the standard contructor.
But what is the exact difference bewteen them? Why would C++11 recommend the last one? Are there any other flags, signals set in the 2. way?
Example 1 was the way to do it before we had = delete which came out in C++11. Now that we have = delete this will completely get rid of the constructor. With making the constructor private you could still use that constructor in a member function where if you try to default an object in a member function with = delete it will be a compiler error.
#include <iostream>
class Foo
{
Foo();
public:
static void SomeFunc() { Foo f; }
};
class Bar
{
public:
Bar() = delete;
static void SomeFunc() { Bar b; }
};
int main()
{
Foo::SomeFunc(); // will compile
Bar::SomeFunc(); // compiler error
}
Live Example
The former is kind of a hack. A friend class could still call the constructor (and you'd get an error at link-time unless you actually defined it as well).
The latter actually prevents its auto-generation so it's really not there.
This question already has answers here:
When does invoking a member function on a null instance result in undefined behavior?
(2 answers)
Closed 8 years ago.
I would expect the following code to crash at runtime with a null pointer error:
#include <memory>
#include <iostream>
#include <cassert>
struct Foo {
void echo() {std::cout << "Echo" << std::endl;}
};
int main()
{
std::unique_ptr<Foo> up(new Foo());
up.reset(nullptr);
assert(up.get() == nullptr);
up.get()->echo();
}
however both gcc (4.7/4.8/4.9), msvc (2013 and upcoming 2015) and clang (3.5) happily outputs:
Echo
and assert is not firing so up.get() is nullptr.
You are essentially calling a member function with an invalid object argument - which is generally considered to trigger undefined behavior. However, you are not using this inside the member funtion, so no Segfaults should occur practically.
Try adding a member and accessing that member inside echo. That should crash your program. I.e.
struct Foo
{
int i;
void echo() {std::cout << i << std::endl;}
};
Calling member function through NULL pointer is surely an undefined behavior.
Your call to that member function is successful as you are not making use of this pointer.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I read about it in other questions but none of them was similar, some was about to call a virtual method in the constructor, others about pure virtuals, but the question here is about vituais methods that are not pure, but about virtual methods that doesn't need be implemented in all derivatives classes. If the class instantiated doesn't implements the method, if we call, it logically calls the method from the base and it crashes sometimes.
I was wondering, why? What is VTABLE (where it enters)? And what is the best way to solve it.
This is a simple example, (avoid answer like pure virtual).
#include <iostream>
class Foo
{
public:
virtual std::string myString() {}
};
class Bar : public Foo
{
public:
};
int main(int argc, char ** argv)
{
Foo * bar = new Foo;
bar->myString();
return 0;
}
What would be the best solution?
Throw an exception
Using assert(false)
Returning a default value
Avoid implementing a body and it will result in an error in
compilation time
None of the alternatives
The best answer will be the one that explains why this happen based on VTABLE and of course, that choose one solution and explain why. The idea is not to base it on opinions.
The base class does implement the function, it just implements it wrong. It is not related to vtables or anything sophisticated. Solution 4 preferred (since it prevents building wrong programs), if not possible/desired 1 or 2 in that order.
Note that the error is not at all related to virtual functions, or inheritance in general (you do not use Bar, did you notice?). It is not even related to classes at all but would happen with any freestanding function as well. Consider:
#include <iostream>
#include <string>
// Note: UB -- nothing returned
int getInt() {}
std::string getStr() {}
int main(int argc, char ** argv)
{
// This probably works (read access from an arbitrary
// location on the stack which is in the prog's address space)
std::cout << getInt() << std::endl;
// This will crash. operator<< will try to access memory through
// a pointer value which is some arbitrary byte pattern on the stack.
// Probably not in the prog's address space.
// Then the destructor for the temporary string will
// try to delete the same
// memory which will crash in any case, even if it happens to
// point to valid memory (which, alas, was never allocated).
std::cout << getStr();
std::cout << "Still alive?\n"; // never printed
std::cout.flush();
return 0;
}
In order to prevent the error from happening with your original code, just return a value. If you implement the function and don't throw or abort (which are the three alternatives), i.e. if you return, you must return a value:
#include <iostream>
class Foo
{
public:
virtual std::string myString() { return "test\n";}
};
class Bar : public Foo
{
public:
};
int main(int argc, char ** argv)
{
Foo * bar = new Foo();
std::cout << bar->myString();
return 0;
}
The VTABLE is a table of pointers to virtual methods. In general, the pointer to the VTABLE is hidden from view, but it is often implemented as the first element in an instance of a class.
When a derived class does not have a member function that its parent class does implement as virtual, the parent's method will be called.
Your mystring function should return a string.
This question already has answers here:
Accessing class members on a NULL pointer
(8 answers)
Calling class method through NULL class pointer [duplicate]
(10 answers)
Closed 9 years ago.
I created a NULL pointer of class App, but somehow the method of the NULL object(of App) is working. Here is my code:
#include "App.h"
#include <iostream>
using namespace std;
int main()
{
App* pointer = NULL;
pointer->print();
system("pause");
}
Attached the Header file
#pragma once
#include <iostream>
using namespace std;
class App
{
private:
int x;
int y;
public:
App(void);
~App(void);
App(int a, int b)
{
x=a;
y=b;
}
void print()
{
cout<<"hello world"<<endl;
}
};
The running result an the screen in : hello world. Why is that?
Undefined behaviour is just that - undefined. Anything can happen, including the appearance of behaving correctly.
For your case, specifically, you might want to check out the generated assembly from your program. You'll probably find that the compiler has optimized your code and inlined that printout or called it directly rather than actually invoking it through a pointer/table lookup.
Dereferenceing a NULL pointer is undefined behaviour. You should not expect your program not to 'work' just because you do this.
In this case your print function does not 'use' the this pointer so your code executes as you expected. But you should not rely on this, undefined behaviour means exactly what it says.
Invoking a method on a NULL pointer is undefined behavior so anything may happen. You should never count on the fact that the code will always produce this output. Always try to avoid such situations.
It is undefined behavior. The implementation is able to work in this toy example because print does not access member variables and is a non-virtual function.
This is undefined behavior, this thread explains why it most likely works, the basic explanation is that it will probably be transformed into something similar to:
void _App_print( App* this );
and since you are not using this it works.
Because print does not (even implicitly) access any data behind the "this" pointer.