I just start to learn it and I tried to find out what are the difference between virtual and not virtual class functions. For this a use a base class with a virtual function which Constructor made the impossible possible - here is example how you can cheat the compiler and make an object with pure virtual function.

#include <iostream>
struct Wolf1 {
    virtual void eat()=0;
	Wolf1() {
		std::cout<<"CONSTR1"<<std::endl;
		ptr=this;
		ptr->eat(); //Here you program will crash (you can comment this)
	}
	~Wolf1() {
		std::cout<<"DECONSTR1"<<std::endl;
	}
} *ptr;
 
struct Wolf2 : private Wolf1 {
    void eat() {
        std::cout<<"WOLF2"<<std::endl;
    }
	Wolf2() {
	    std::cout<<"CONSTR2"<<std::endl;
		ptr->eat();
	}
	~Wolf2() {
		std::cout<<"DECONSTR2"<<std::endl;
	}
};
 
int main() {
	Wolf2 my;
	system("PAUSE");
	return 0;
}

Here you see how you can handle objects with abstract classes. But the general idea I had is that you can now see "the difference between virtual and not virtual class functions". For seeing this just delete the virtual keyword in front of the function and make it a body now the source will look like this:

#include <iostream>
struct Wolf1 {
    virtual void eat() { //Here you can remove the "virtual" and see the result
            std::cout<<"WOLF1"<<std::endl;
    }

	Wolf1() {
		ptr=this;
	}
	~Wolf1() {
	}
} *ptr;
 
struct Wolf2 : private Wolf1 {
    void eat() {
        std::cout<<"WOLF2"<<std::endl;
    }
	Wolf2() {
		ptr->eat();
	}
	~Wolf2() {
	}
};
 
int main() {
	Wolf2 my;
	system("PAUSE");
	return 0;
}

Output:
if virtual:

WOLF2

else:

WOLF1

Oh Lord! What have you done?! This is a friendly advice, but before you go any further in the realm of virtual functions, you should go back and review how structures/classes and inheritance work. I am sorry to burst your bubble, but you didn't beat the compiler. With a few modifications, I managed to compile your first code, even the destructors were called, so let's go through this.

struct Wolf1 {
    virtual void eat()=0;
	Wolf1() {
		std::cout<<"CONSTR1"<<std::endl;
		ptr=this;
		ptr->eat(); //Here you program will crash (you can comment this)
	}
	~Wolf1() {
		std::cout<<"DECONSTR1"<<std::endl;
	}
} *ptr;

In the constructor you have the line : "ptr=this", if you leave that alone as it is now, it won't compile. The reason why not, is because ptr doesn't really exist in the scope of your structure(nor you have any valid global variables named ptr). If you look at 'ptr' closely you will see, that it has no type. You just made ptr up, therefore you cannot assign any value to it, yet alone use it. In that context, the following line : ptr->eat () simply wouldn't make any sense to the compiler.

Now you probably think, but I have *ptr. Yes, but that is not going to work either. First of all *ptr is not in the scope of your structure, so you wouldn't be able to use it anyway. I don't know how to put this, but when you define your class or your structure, you don't need an actual instance of the class you are defining. It's like a blueprint, you don't need to build an actual car, in order to design, and define how you want it to behave. Your class/structure definition should work the same way. I can see you are familiar with the pointer 'this'. That pointer serves that exact purpose, so you can refer to the class itself without a need of an actual instance.(When you make an instance of the class it becomes an object.)

Back to *ptr, what you really did there is you made a pointer of structure Wolf1. *ptr is not an instance of your structure. It is a pointer because you put the asterisk before ptr. Don't let the structure definition confuse you, you are basically saying "int *p", there is really nothing new going on.

You may ask yourself but how Wolf2 can compile without an error, if ptr does not really exist. Let's look at structure Wolf2.

Wolf2() {
std::cout<<"CONSTR2"<<std::endl;
ptr->eat();
}

If you comment the line : "ptr->eat ()" out, it compiles. The reason why, is because you defined *ptr somewhere before structure Wolf2, therefore it exist in the scope of Wolf2. That is why you won't get an error there, however just because the compiler can make some sense of it, does not necessarily make it right. In Wolf2 you are calling "ptr->eat ()", but sadly *ptr is a pointer that has never been initialized. So when you call it, your program will crash, because ptr does not really point to anything. If you comment that line out your program will return 0, and even the destructors will be called. However this does not fix your code, it's still a mess. In your second code, you will need to address those issues. I really hope my analysis wasn't entirely futile, and now you can better understand what is really going on.

Edited 4 Years Ago by LRRR: n/a

Hahaha are you joking - my code - mess!? This code is compile without any errors in my Visual Studio 2010 Ultimate. And ptr, my buddy, is a pointer to Wolf1 which is fully legal in C++(its says: you can't declare an abstract class object, but you can declare a pointer to abstract class object) it's not a "int *p". About the "this" keyword - is a constant pointer to Wolf1 (Wolf1 * const) and my assignment with it (ptr=this) is fully legal(Wolf1* = Wolf1* const). Other thing is that the Wolf1 structure have fully access to the global variable ptr*(I think you're the one how can understand - "*ptr is not in the scope of your structure, so you wouldn't be able to use it anyway."). What compiler you use? (if the compiler is bugged you wouldn't be so stupid)

Don't get angry. I just want to clarify the situation. If you think you're right just tell my why?

This code is compile without any errors in my Visual Studio 2010 Ultimate.

C++ is not defined by Visual Studio 2010 Ultimate. For example, on GCC your code fails with two errors:

main.cpp:6:3: error: 'ptr' was not declared in this scope
main.cpp:29:16: error: 'system' was not declared in this scope

Comeau agrees with this assessment:

"ComeauTest.c", line 6: error: identifier "ptr" is undefined
                ptr=this;

Given only that out of three compilers, two of them[1] fail to compile your code, I'd lean toward Visual Studio being wrong. Please provide chapter and verse from the C++ standard that proves GCC and Comeau are broken.

if the compiler is bugged you wouldn't be so stupid

Please provide chapter and verse from the C++ standard before calling other people stupid.


[1] One of those compilers, Comeau, is also widely accepted as the best conforming compiler available as far as standard C++ goes.

Ok in this case I'll call Microsoft stupid for providing such of non-standard C++ compilers with their products. Maybe the Visual compiler adding the declaration of this variable in the start of the file. Anyway sorry for my first reactions seeing the post above.

@sasho648 I am not angry, why would I be? But that does not change my opinion about what you are doing is wrong, but if you want to defend your code so eagerly, and come at me instead of looking at it, it's up to you. Honestly I don't care, I'll just move on with a blink of an eye, trust me. One thing though, don't call me buddy, I am not your friend nor your classmate, or someone you are hanging out with.

To answer your last question, I use the GNU C++ compiler the 4.6-15.1.3.x86_64 version to be exact. I've made an exception in your case, and compiled your code in Visual Studio as well, and surprisingly it compiled. - Honestly I did not expect that, Microsoft's compiler is very forgiving, because there is no way you could compile that with g++ (mingw).

I've never said that you can create an object of an abstract class. I merely emphasized you are making a pointer there. (I wasn't sure, what was your intention, and I didn't know how much you were aware of what you are doing. That's why I made the simplified example of 'int *p', so you could put those next to each other.)

Other thing is that the Wolf1 structure have fully access to the global variable ptr*

The problem with that, is you are assigning value to ptr, before it has been declared. That's why you won't be able to compile it with g++ on the first place, but yes I admit it, it compiles on Visual Studio.

//simplified example
x = &some_variable;
int *x;

So I decided to look at your code, once more to better understand what you were trying to do, so here it is:
-> you are defining the structure Wolf1, and declaring a Wolf1* pointer at the same time.
-> then you are defining Wolf2 as a child class of Wolf1
-> in your main, you are making an instance of Wolf2

The result is : Wolf2 object "my", calls the constructor of the parent class Wolf1, which assigns the variable '*ptr' its own address. The only thing, why it works is because '*ptr' was declared as a global variable(right after the structure definition of Wolf1) and it falls in the scope of Wolf1 constructor. I believe this is a prime example of obfuscated coding, and I don't think you can compile it, with any other compiler. One more thing I have to mention, your base class is not an abstract class. You have no pure virtual functions in it(an empty definition is still a definition) so you were working with regular classes the whole time, kinda defeats the purpose of what you were trying to do in the first place.
What you do next, is up to you, but I think you would benefit from the experience of trying out different compilers and see how your code is doing in different environments.

Edited 4 Years Ago by LRRR: n/a

This article has been dead for over six months. Start a new discussion instead.