So I have a c++ project that I'm working on and I'm trying to understand an other guys code but all I get are errors and confusion about c++ abstract classes.
So What I have is a header file a cpp file and a main program.
I want to create an abstract class pointer and then pass it to a method that initializes it to a subclass and then back in the main program I can use it as the subclass:
main.cpp:
#include "a.h"
#include <iostream>
using namespace std;
void parse(A* a){
a = new B();
a->foo();
}
int main() {
A* a;
parse(a);
a->foo();
}
a.h:
class A{
public:
virtual void foo() const = 0;
virtual ~A(){ }
};
class B : public A{
public:
void foo() const override;
};
class C : public A{
public:
void foo() const override;
};
a.cpp
#include <iostream>
#include "a.h"
void B::foo() const{
std::cout << "B" << std::endl;
}
void C::foo() const{
std::cout << "C" << std::endl;
}
Basically here I think I should cee a B but I get a segmentation error or the program exits without printing anything.
Thank you for your help!
In main you have uninitialized pointer a
int main() {
A* a;
parse(a);
a->foo();
}
So this statement
a->foo();
results in undefined behavior.
As for the function parse
void parse(A* a){
a = new B();
a->foo();
}
then it deals with its local variable a. Changing the local variable does not affect the original pointer declared in main.
You need to declare the parameter as having a referenced type
void parse(A* &a){
a = new B();
a->foo();
}
In this case the pointer a declared in main will be passed to the function by reference and the function will change the original pointer a.
Besides the issue of undefined behviour described in Vlad's answer, your example also leaks memory, even if the pointer in main was correctly initialised.
I recommend an alternative solution. Instead of modifying the pointer through a reference, I recommend to not use owning bare pointers. Instead, return the pointer, and use a smart pointer for ownership:
std::unique_ptr<A>
parse(){
auto a = std::make_unique<B>;
a->foo();
return a;
}
int
main() {
auto a = parse();
a->foo();
}
Related
I want to call the child's function from parent's function in reinterpreted class, like below.
Example
#include <iostream>
class A {
public:
void func1() {
// some code
func2();
// some code
}
protected:
virtual void func2() {
printf("class A\n");
}
};
class B : public A {
protected:
virtual void func2() {
printf("class B\n");
}
};
int main() {
A* ab = new A();
ab->func1(); // this print "class A"
B* bab = reinterpret_cast<B*>(ab);
bab->func1(); // this also print "class A"
// I want to print "class B" when I use bab->func1()
}
In this situation, Is there any way to print class B using the reinterpreted class bab without redefining func1?
For C++ polymorphism to kick in, you must create an instance of the derived class somewhere, but you can store a pointer to the base class. Using the base-class pointer will dispatch to the overridden functions of the derived class. So your definition of A and B is fine, your usage in the main function is not. reinterpret_cast is not intended for this.
#include <iostream>
#include <memory>
class A {
public:
void func1() {
// some code
func2();
// some code
}
protected:
virtual void func2() {
printf("class A\n");
}
};
class B : public A {
protected:
virtual void func2() {
printf("class B\n");
}
};
int main() {
{
// This works, but don't do this. Naked "new" is not modern C++ and dangerous.
A* ab = new B();
ab->func1();
delete ab;
}
{
// VARIANT 2: use smart pointers
std::unique_ptr<A> ab = std::make_unique<B>();
ab->func1();
}
{
// VARIANT 3: A non-smart pointer is okay, as long as it
// 1. references an existing allocated object
// 2. the pointer does not outlive the object it points to
B b;
A* ab = &b;
ab->func1();
}
{
// VARIANT 4: Like Variant 3, but with reference instead of pointer
B b;
A& ab = b;
ab.func1();
}
}
Output
class B
class B
class B
class B
https://godbolt.org/z/8e5E85nx5
EDIT: Try to avoid allocation with new. Any memory allocated in this fashion must be freed by you using delete and it is very easy to forget (I did when I first wrote this answer, kinda proving my point). Even if you do delete the memory at the end of your function, there is the possibility that your code never reaches this statement, e.g. if exceptions are thrown somewhere between new and delete.Here is some further reading:
Why is it a bad idea to use 'new'?
Why should C++ programmers minimize use of 'new'?
pass * as a function parameter
#include <iostream>
class A {
public:
A() {}
};
class B : public A{
public:
B() {}
};
void foo(A* a) {
a = new B();
}
void ff() {
A a;
foo(&a);
}
pass ** as a function parameter
#include <iostream>
class A {
public:
A() {}
};
class B : public A{
public:
B() {}
};
void foo(A** a) {
*a = new B();
}
void ff() {
A* a;
foo(&a);
}
When I see leveldb, I am in a puzzle about this.
The specific code is the following.
https://github.com/google/leveldb/blob/master/db/db_impl.cc#L1537
I think it's ok to use FileLock lock
Then pass &lock to LockFile(const std::string& filename, FileLock* lock)
LockFile function is this
Passing double pointer and just a pointer are not the same
void foo(A* a) {
a = new B();
}
Change an input pointer to another value. The result will not reflect in the callee ff().
It's merely change the argument.
void foo(A** a) {
*a = new B();
}
Change a pointer to another pointer and change the value, which is "the another pointer", of this pointer points to . The result will reflect in ff()
According to the ff(), I assume you have a follow up question which need to operate a after foo() is called. So second one might be a proper way.
For FileLock, I believe you're referring to this implementation.
It's using double pointer because it wants to replace the entire content of FileLock.
Live demo
Followup: Why it chose using double pointer instead of pass by reference?
Because reference is not possible to be replaced, my assumption is that it chose it chose to replace the whole content which is simpler than make the implemention complex for re-initialization.
A.hh
#ifndef A_HH
#define A_HH
#include <iostream>
#include <string>
using namespace std;
class A {
private:
int size;
string name;
public:
A();
~A();
int Load(int, string);
int getSize();
string getName();
/* data */
};
#endif
A.cc:
#include "A.hh"
A::A() {
}
int A::Load(int _size, string _name) {
size = _size;
name = _name;
return 0;
}
int A::getSize() {
return size;
}
string A::getName() {
return name;
}
A::~A() {
}
B.hh:
#ifndef B_HH
#define B_HH
#include "A.hh"
#include <string>
class B {
private:
A* objectA;
public:
B();
B(A*);
~B();
A* getA();
/* data */
};
#endif
B.cc:
#include "B.hh"
B::B() {
}
B::B(A* obj) {
objectA = obj;
}
A* B::getA() {
return objectA;
}
B::~B() {
}
C.cc
#include "C.hh"
C::C() {
}
int C::doSomething() {
cout<<"size = "<<getA()->getSize()<<endl;
cout<<"name = "<<getA()->getName()<<endl;
return 0;
}
C::~C(){
}
C.hh
#ifndef C_HH
#define C_HH
#include "B.hh"
class C : public B {
public:
C();
~C();
int doSomething();
/* data */
};
#endif
main.cc
#include "A.hh"
#include "B.hh"
#include "C.hh"
int main() {
A* objA = new A();
objA->Load(1, "Hello Drew Dormann :)");
B* objB = new B(objA);
C* objC = new C();
objC->doSomething();
return 0;
}
Why am I getting a segfault on doSomething()?
I'm using the child of B to handle the object parsed into B. Also I have to use B's child to handle A because this is part of something much bigger and this is the only way to simplify it.
I don't understand why this happens.
There seems to be a misconception of how objects work and are constructed behind this question.
C* objC = new C();
Creates brand new C. The C constructor does absolutely nothing beyond allocating storage, so absolutely nothing is initialized. Because C inherits from B, C's constructor will call the default constructor for B, which does nothing, but calls the default constructor for its parent, A.
A's default constuctor does not initialize name and size so their values are undefined. B's default constuctor does not initialize objectA so it is undefined, leading to the segfault.
This C was created by new comes out of some pool of memory, typically the heap, and needs to be returned to this pool with delete when no longer needed. If it is not the program will lose the memory used by C.
The same sample can be performed without dynamic allocation.
C objC;
Creates a C, but does it on the stack. When the stack unrolls at the end of the function or code block (search term: variable scope) the C will be popped off and automatically destroyed. This is typically the better way to operate as it requires no additional memory management. The C looks after itsef and can be considered "fire-and-forget."
Back on topic...
objC->doSomething();
Do something calls the getA method inherited from B which dutifully returns the uninitialized objectA. objectAis promptly used to call getSize with objectA as the concealed this parameter. Since Crom only knows what objectA is actually pointing at it would be a minor miracle if this->size wasn't somewhere crash-provoking.
If the OP expects
A* objA = new A();
objA->Load(1, "Hello Drew Dormann :)");
and
B* objB = new B(objA);
to have some bearing on the state of C. The OP is incorrect. objA and objB are their own entities. They are different objects and every object has its own state.
In order to have C initialize B with something other than the default constructor, you need your C constructor to look more like this:
C::C(A* obj) : B(obj)
{
}
This assigns a pointer to A passed into C to B, using B's B(A*); constructor.
C::C(A* obj,
int size,
string name) : B(obj, size, name)
{
}
B::B(A* obj,
int size,
string name) : A(size, name)
{
}
Cascades all of the parameters needed to fully specify a C all the way down to A.
As B needs to have objectA initialized, I recommend removing B and C's default constructors to force initialization to a meaningful value. If B and C require default constructors for some other purpose, such as storage in a standard container, either getA() needs to be a lot smarter or B's default constructor must initialize objectA to some safe value.
This still leaves the great question of why B contains a pointer to a parent. I'll leave that to the OP to work out.
And while The OP is at it, I recommend reading this: What is The Rule of Three?. Because the next question is likely to be "Dude! Who deleted my objectA"?
Also using namespace std in a header is very super bad. Read here: Why is "using namespace std" considered bad practice?
Your problem is that objectA in objC points to invalid memory hence in doSomething() you are trying to call the member access operator on an invalid pointer. You can change the default constructor of B to construct an object and have objectA point to it, make sure to free your memory as well!
#include <iostream>
#include <string>
/*#################
// !! class A !! //
#################*/
class A
{
private:
int size = 0;
std::string name;
public:
int Load(int, const std::string&);
int getSize() { return size; }
std::string getName() { return name; }
};
int A::Load(int _size, const std::string &_name)
{
size = _size;
name = _name;
return 0;
}
/*#################
// !! class B !! //
#################*/
class B
{
private:
A* objectA;
public:
B() : objectA(new A()) { }
B(A* obj) : objectA(new A(*obj)) { }
A* getA() { return objectA; }
virtual ~B() { delete objectA; }
};
/*#################
// !! class C !! //
#################*/
class C : public B
{
public:
C() = default;
int doSomething();
};
int C::doSomething()
{
// Problem: objectA points to invalid memory
std::cout << "size = " << getA()->getSize() << std::endl;
std::cout << "name = " << getA()->getName() << std::endl;
return 0;
}
/*#################
// !!! main !!! //
#################*/
int main()
{
A* objA = new A();
objA->Load(1, "Hello Drew Dormann :)");
B* objB = new B(objA);
C* objC = new C();
objC->doSomething();
// free your memory!!!
delete objA;
delete objB;
delete objC;
return 0;
}
I know this question must have been covered endless of times, but I've searched the previous questions, and nothing seems to pop.
It's about inheritance and virtual functions i C++. I have a problem with calling virtual functions in subclasses from the superclass.
Let me give an example. Start of with three classes, which inherit from each other.
class A {
void foo() { bar() }
virtual void bar() { }
};
class B : public A {
virtual void bar() { }
};
class C : public B {
virtual void bar() { // do something }
};
Now I wanna have a variable declared as B* but instantiated as C*.
B* myObject = new C();
myObject->foo();
When I do this, and call foo() on myObject, then A::foo() is calling bar(). But only B::bar() is called, not C::Bar() - which in reality myObject is, even though it's declared as B, which again affects that "// do nothing" doesn't get executed.
How do I tell A::foo(), that it needs to look at lowest implementation?
Makes sense?
// Trenskow
EDIT:
C::Foo is not the problem. Foo is being called in class A, as it's the only place it's implemented. The problem arises, when A:Foo calls Bar(). Then B:Bar is called and not C::Bar.
Maybe the problem is, that in my implementation, I only get a void* pointer to the object in A.
Like this:
void A:Foo(void *a) {
A* tmpA = static_cast<A*> (a);
tmpA->bar();
}
Now the compiler thinks, that tmpA is an A. But somehow it manages to figure that it's a B*, and calls B::Bar, when in fact tmpA is a C* and it should be calling C::Bar.
The following prints "A::foo C::bar" as expected. Are you getting something different? B::bar is never called because C is the actual runtime type of the object. In C::bar, you could call B::bar explicitly by adding B::bar(); to its body.
#include <iostream>
using namespace std;
class A {
public:
void foo() { cout << "A::foo "; bar(); }
virtual void bar() { }
};
class B : public A {
public:
virtual void bar() { cout << "B::bar" << endl; }
};
class C : public B {
public:
virtual void bar() { cout << "C::bar" << endl; }
};
int main()
{
B* c = new C();
c->foo();
return 0;
}
void A:Foo(void *a) {
A* tmpA = static_cast<A*> (a);
tmpA->bar();
}
This is undefined behaviour. You cannot cast a B* to a void*, then cast that void* back to an A*. If you want it to work properly, you have to ditch the void*. Alternatively, you could try dynamic_cast.
Assuming you mistyped your last block of code and the names match:
B* variable = new C();
variable->foo();
Then the C::Foo method is being called or you are using a terribly bad compiler.
(This also assumes that you don't actually have a compiler error in C::Foo, and that the comment is actually something like std::cout << "Hi mom!" << std::endl;)
Don't you mean:
B* myObject = new C();
myObject->foo(); // not variable->foo()
class A
{
public:
void foo() { bar(); }
virtual void bar() { std::cout << "A"; };
};
class B : public A
{
public:
virtual void bar() { std::cout << "B";};
};
class C : public B
{
public:
virtual void bar() { std::cout << "C"; }
};
This prints 'C' as expected.
I don't follow. You're saying
But only B::bar() is called, not
C::Bar()
No. You invoked the constructor of class C, which means that the vtable makes bar() point to C::bar(), so calling foo() in this case would go straight to C::bar().
If you want to force A::foo() to explicitly only call A's implementation, you can do that by just writing
void foo() { A::bar(); }
What exactly are you trying to do?
what compiler are you using? Visual Studio (IIRC) usually has the runtime type information turned off by default so maybe its just something simple as that?
take this simple code:
class A{
public:
virtual void foo() = 0;
void x(){ foo(); }
};
class B: public A{ foo(){ ... } };
main(){
B b;
b.x();
}
What I want is to build an abstract class that will have a function that will call a function expecting it to be implemented in the derived class
The question is that I can't seem to make that work, the compiler says it can't compile because it can't find the reference(or something like that) to the foo() to be executed in x() of the base class. Can this work? Can anyone give me an example of this?
EDIT: It seems that it just doesn't work when the "foo();" is inside the destructor of class A(the base one)...
It just got me confused. =[
EDIT2: how interesting this got. I just created a callfoo(){ foo(); } and now it compiles ok, but if I try to call the pure abstract function directly from within the destructor of Base class A, it gives me errors... weird. Anyone has any idea of this? O_o
any help on this please?
Thanks,
Jonathan
Update
It worked outside the destructor. Now I just got confused.
Try putting the "foo()" inside the destructor of the A(base) class, at least for me is not compiling...
any help plz?
There is nothing preventing you from doing that:
struct A {
virtual ~A() {}
virtual void f() = 0;
virtual void g() { f(); }
};
struct B : A {
void f() { std::cout << "B::f()" << std::endl; }
};
// ...
A* a = new B;
a->g(); // prints "B::f()"
As for calling a pure virtual function from the destructor (or constructor): Don't! It invokes undefined behaviour.
ยง10.4/6:
Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined.
It should work with a few syntactic modifications.
#include <iostream>
class A {
public:
virtual ~A() {}
virtual void foo() = 0;
void x() { foo(); }
};
class B: public A{
void foo(){ std::cerr << "bingo!" << std::endl; }
};
int main(){
B b;
b.x();
return 0;
}
$ g++ -Wall -Weffc++ derived.cc
$ ./a.out
bingo!
This technique is perfectly legal.
Seems that what you are looking for is an implementation of the Template Method pattern.
You need to use pointers, in order to take advantage of polymorphism (thus avoiding the message ... x is not a member of B)
#include <iostream>
class A{
public:
virtual void foo() = 0;
virtual void x(){ foo(); }
};
class B: public A{
void foo(){ std::cout<<"this is b"<<std::endl; }
};
int main(){
A* b= new B();
b->x();
return 0;
}
Well in theory that works just as fine, you should though add a return type to foo() on class B