Inline member do not need declaration - c++

In C++ we have feature people do not think about much, like we can execute method of a class that uses method/member that has been declared later in class i.e.:
struct s{
foo() { foo1();}
foo1() { assert(0); }
};
int main() {
s s1; s1.foo();
}
I already know that compiler puts member definitions after class definition and it can be found so the order doesn't matter: Do class functions/variables have to be declared before being used?. What I was wondering is how it would look like if we would make methods inline and compiler will respect our request and make them really inline would it work then? Would compiler do any additional stuff to reorder whole class?

Related

Declaration of function prototypes within classes in C++? [duplicate]

I have been programming in C++ for quite some time and I never thought about this until today.
Consider the following code:
struct foo
{
// compiles fine
void bar()
{
a = 1;
my_int_type b;
b = 5;
}
// Just a declaration, this fails to compile, which leads me to assume that
// even though the bar() method is declared and defined all at once, the
// compiler looks/checks-syntax-of the class interface first, and then compiles
// the respective definitions...?
void bar2(my_int_type); // COMPILE ERROR
my_int_type b; // COMPILE ERROR because it comes before the typedef declaration
typedef int my_int_type;
my_int_type a;
void bar3(my_int_type); // compiles fine
};
int main()
{
foo a;
a.bar();
return 0;
}
Is my understanding of why the errors occur (see bar2() comment above) correct/incorrect? Either way, I would appreciate an answer with a simplistic overview of how a single-pass C++ compiler would compile the code given above.
For the most part, a C++ file is parsed top-to-bottom, so entities must be declared before they are used.
In your class, bar2 and b are invalid because they both make use of my_int_type, which has not yet been declared.
One exception to the "top-to-bottom" parsing rule is member functions that are defined inside the definition of their class. When such a member function definition is parsed, it is parsed as if it appeared after the definition of the class. This is why your usage of my_int_type in bar is valid.
Effectively, this:
struct foo
{
void bar()
{
my_int_type b;
}
typedef int my_int_type;
};
is the same as:
struct foo
{
void bar();
typedef int my_int_type;
};
inline void foo::bar()
{
my_int_type b;
}
Compiler just starts to go down in a block. Any symbol which is not familiar to it will be considered as a new symbol which is not defined. This is the scheme behind the function definition or header files.
You can suppose that the compiler first makes a list of definitions so the bar() method should get compiled correctly because the definitions have provided before.
It has a lot to do with visibility. I think your confusion may come from assuming a single pass. Think of class parsing as done in two stages.
Parse class definition.
Parse method implementation.
The advantage to this is we have visibility of the entire class from within class member functions.

Why is this class visible by this templated class?

I didn't expect this to compile but it does. I'm wondering if this is guaranteed to happen or whether it's just compiler-specific. I'm wondering why 'OSInterface::handleOSEvents()' can see the 'InputHandler' class and its member function. If OSInterface is an ordinary class then it doesn't compile, the order of the class definitions must be swapped.
template <typename input_handler_t>
class OSInterface
{
public:
void readOSEvents()
{
input_handler_t::handleKeyDown(5);
}
};
struct InputHandler
{
static void handleKeyDown(int a) {};
};
int main()
{
OSInterface<InputHandler> os;
os.readOSEvents();
}
Edit: I was thinking the compiler must be doing something special with it, because if it instantiates the template class in the order that it's declared then it shouldn't be able to see 'InputHandler' and call its member function. On the other let's say that it instantiates the class right at the bottom of the .cpp then it would be able to see 'InputHandler' but I wouldn't be able to create an object of that class in main().
I'm wondering why 'OSInterface::handleOSEvents()' can see the 'InputHandler' class and its member function.
There is no OSInterface::handleOSEvents() in the example. I assume that you mean OSInterface::readOSEvents().
Because OSInterface is instantiated after InputHandler was defined.
I'm wondering if this is guaranteed to happen or whether it's just compiler-specific.
The program is well-formed. The program will compile with all standard conforming language implementations.

Why virtual & static keywords aren't allowed outside class declaration?

I am curious to know why following isn't allowed in C++?
1st program:
#include <iostream>
class Test {
public:
int myfun();
}
virtual int Test::myfun()
{ return 0; }
int main()
{ }
[Error] 'virtual' outside class declaration
2nd program:
#include <iostream>
class Test {
public:
int myfun();
};
static int myfun() {
std::cout<<"This program contains an error\n";
return 0;
}
int main() {
Test::myfun();
return 0;
}
[Error] cannot call member function 'int Test::myfun()' without object
So, my questions are
Why can't I make a member function virtual like as in 1st program?
Why can't I make a member function static like as in 2nd program?
Is there any reason to not allow these 2 keywords outside the class?
The modifiers must be on the function declarations, otherwise it would be impossible to call the functions given just the declarations.
Since they must be on the declarations, it would be redundant to put them on the definitions as well. There's no particularly good reason to disallow them (as long as they match the declaration), but no particularly good reason to allow them either.
virtual has to do with polymorphy and that is why it's only allowed inside a class. static is allowed outside of classes and makes global functions "private". The problem with your program is, is that myfun() in the class Test is not static and you have to create a instance of Test to invoke this method.
int main()
{
Test test;
test.myfun(); // works
return 0;
}
the static version of myfun() has nothing to do with the class and cannot be invoked like that: Test::myfunc() (because, as i said, it has nothing to do with Test). You can invoke it like this:
int main()
{
myfun(); // global function, has nothing to do with any classes
return 0;
}
You want to make a function virtual by stating this outside of class declaration. However, think of other code that will be using your class. You will most probably #include only the header of your Test class, which will contain only the class Test block, not the implementation. So while compiling that code the compiler will not know that a function is virtual. However, it needs to know, because it needs to generate different call code for virtual and non-virtual functions.
In more details, assume a more advanced program than your example. Following to your proposition, it will contain several compilation units and be organized, for example, as follows (#ifdef guards omitted for clarity):
// Test.h
class Test {
public:
int myfun();
};
// Test.cpp
#include "Test.h"
virtual int Test::myfunc() { return 0;}
// other.cpp
int foo(Test& test) { return test.myfunc(); } // <--- *
You will be compiling Test.cpp separately from other.cpp. So when you compile other.cpp, how would the compiler know that it should perform a virtual call to test.myfunc() in foo()?
The same reasoning applies to static functions. However, note that the static keyword has also another meaning that can be used outside of a class declaration.
The compiler compiles one source file ("translation unit") at a time. If you would declare a class
#include "Test.h"
class SpecialTest : public Test {
int myfun();
};
the compiler only sees what is in "Test.h", not what is in "Test.cpp". So if you were allowed to make myfun() virtual in the .cpp file only, the compiler could not correctly compile "SpecialTest" without having to look at "Test.cpp"
As indicated by juanchopanza in the comments, virtual only makes sense in the context ob classes. Recall that a virtual method is a function without an implementation, leaving this to other classes that inherit from the class where the virtual method is defined. But if the virtual definition is outside of a class, how to express inheritance in this case? It would be a non-implemented function without the possibility for other classes to actually implement it.
For static, you are confusing its meaning outside and inside the context of a class. If you want to have a function that can be called without the need for a corresponding object, you can define it as a static function of the class. If you want this function to be outside the class, simply omit the static as the function is available without the need for an object anyway. But static outside of the class context means something completely different.

How do these two functions defined in the same class manage to call each other without forward declaration?

For the time I'm learning to code with boost/asio. Many code samples make use of the combination of async_accept and bind. In the server code , i come across some thing like this:
class Tcp_server
{
public:
Tcp_server()
{
}
void start_accept(int a)
{
if(a>0)
{
cout<<a<<endl;
handle_accept(a-1);
}
}
void handle_accept(int a)
{
if(a>0)
{
cout<<a<<endl;
start_accept(a-1);
}
}
};
If i make an instance of Tcp_server and call either handle_accept or start accept, it works. But if I drop the Tcp_server class encapsulation, the compiler would complain "handle_accept is not declared". I'm just wondering if the compiler automatically forward declare all the functions defined in the same class. Can anyone explain why?
Functions defined in the definition of a class have exactly the same semantics as if they are only declared in the class definition and then defined immediately after the class definition. The only difference is that such member functions are implicitly declared inline while a function definition is either not-inline or explicitly inline. That is, from the compiler's point of view the functions are declared and the class is defined before the function definitions are considered.
The reason for defining the function after the class definition is simple: without doing so, the class would be incomplete and look-ups of members would fail which is clearly not desirable for member function definitions. As a side effect, functions can readily refer to each other. Since defining member functions in the class definition is primarily for convenience it would also be somewhat inconvenient to require declaration for member functions used later.

Resolving Inclusion Ordering

I am working on a codebase that is not my own, that has the following layout:
object.h:
// Objects are defined
// #include "tickets.h" (functions to access the objects)
// An access-handler object is defined
I want to introduce a class that knows about the objects, can be accessed from functions in tickets.h, but can also use the access-handler object. The functions are separate, i.e. class functions that are called in tickets.h do not use the access-handler (I wouldn't know where to start if that weren't the case).
Therefore my class needs to be defined before tickets.h, but some of its functions need to be defined after the access-handler. Is there a way to do this without splitting it up into two header files something like the following:
// Objects are defined
// -- include declaration of class, and definition of functions that tickets.h needs
// #include "tickets.h"
// An access-handler object is defined
// -- include functions of class that need the access-handler
This seems very messy splitting things up like this into two separate files, I was hoping to keep everything contained.
Thanks for any help, I clearly only have a very rudimentary understanding of declarations/definitions in c++.
EDIT: If I use forward declaration and include it before tickets.h (with the class declared in mynewclass.h and functions defined in mynewclass.cc) will mynewclass.cc be able to use objects declared after the inclusion of mynewclass.h? Namely the access-handler object.
EDIT2: Something like this:
object.h:
class obj { // definition }
#include "tickets.h"
class obj_handler {
public void handle { // code }
}
tickets.h:
void do_something(obj o){
communicator.foo();
}
My object (communicator):
class communicator {
public:
void foo() { // code }
void bar() { // use handle() from obj_handler }
}
As you can see, my communicator needs to be used in tickets.h, but can't be defined until after obj_handler. So where should I include it?
If I correctly understand your question - you can use forward declaration to solve this problem. This will allow you to declare some class before defining it's methods. For example:
// this is forward declaration of class A, no definition provided
class A;
class B
{
// uses A
A * a_;
};
// class A definition
class A
{
// may use class B now
B * b_;
};
I'm not quite sure whether I understand this right and don't have enough reputation here yet to make this a comment, so let me try to answer your question this way, please feel free to follow up if I'm guessing wrong:
I believe what you are referring to is an entire class definition, i.e., one including all function definitions within the class declaration. Other than that, it is not very common to see object definitions followed by preprocessor directives. What is typical though is a forward declaration of functions and a class prototype.
So, for example, you could declare in some header.h:
class C
{
public:
void method1(void);
int method2(void);
};
And in some implementation.cpp the definition of the functions like:
void C::method1(void) { /*...*/ }
In the other file preceded in the inclusion chain by your access-handler you then define the other function:
int C::method2(void) { /*...*/ }
What do you mean by access-handler, by the way?
Oh, and your linker likely will yell somewhat at you if you do function definition in a header file.
With regard to your addenda: everywhere you put a forward declaration, loosely speaking, the compiler will insert a copy of the declaration in question, consider it a soft link in the context of file systems. There are negative implications associated with it, like increased duration and the memory load of compilation if you have many forward declarations of the function signature or class. It's impossible to tell whether this will word in your particular situation since only you know the actual code in question. But most likely it would work.
Take a look at these pages:
http://en.wikipedia.org/wiki/Forward_declaration
When can I use a forward declaration?