I currently have two unnamed classes defined in my Foo.h:
class Foo {
public:
Foo();
class {
private:
int x;
int y;
public:
int GetX() { return x; }
int GetY() { return y; }
} Sub1;
class {
private:
int x;
public:
int GetX() { return x; }
} Sub2;
}
This code compiles just fine, and it used like this:
Foo temp;
int Ax, Ay, Bx;
Ax = temp.Sub1.GetX();
Ay = temp.Sub1.GetY();
Bx = temp.Sub2.GetX();
However, now I want to move the member function definitions to the source file.The only way I know to split this class into a header file and source file, is to name the classes:
Foo.h:
class Foo {
private:
class A {
private:
int x;
int y;
public:
int GetX();
int GetY();
};
class B {
private:
int x;
public:
int GetX();
};
public:
Foo();
A Sub1;
B Sub2;
}
Foo.cpp:
int Foo::A::GetX() { return x; }
int Foo::A::GetY() { return y; }
int Foo::B::GetX() { return x; }
This code is not what I want, however, since it is ugly and I didn't want a named class in the first place.
Is it possible to split the class into a header file and source file? Or is this just bad code design?
It is, unfortunately, impossible. §9.3/5:
If the definition of a member function is lexically outside its class
definition, the member function name shall be qualified by its
class name using the :: operator.
Since no class name exists, no out-of-class definitions for member functions are possible. The fact that GCC allows decltype-specifiers in this context is a bug.
With gcc at least, you can do the trick using decltype:
int decltype(Foo::Sub1)::GetX() { return x; }
It is not standards compliant, though, as Columbo has already pointed out. So don't blame me, if a future version of gcc refuses to compile this. But we all now, that gcc has never been dogmatic about standards compliance, and that the gcc team has a strong tendency to keep language extensions, if they are both unambigous (which is clearly the case here) and useful to at least some programmers. Over the time, many of these gcc extensions have eventually become part of the standards.
Nonetheless, clang and probably most other compilers refuse this construct with the error message:
'decltype' cannot be used to name a declaration
But even clang can be tricked into accepting the decltype trick. We just need to do a typedef:
typedef decltype(Foo::Sub1) Sub1type;
int Sub1type::GetX() { return x; }
Of course, this is not much different to naming the unnamed classes. The advantage of the typedef solution might still be, that you can hide away the type names inside a private namespace.
Related
I wrote the following snippet in the same file where the main function is. However, the Live Semantic Error feature in Visual Studio says that 'a nonstatic member reference must be relative to a specific object'. In my opinion, the x in function m should be the int x defined in the file-scope and it should be accessible in everywhere of this file.
Please point out where I misunderstood. Thank you in advance!
int x = 0;
class Test1{
protected:
char *x;
class Test2{
public:
int m(){
return x++;
}
};
};
What you've created here is a nested class: The name of the nested class exists in the scope of the enclosing class, and name lookup from a member function of a nested class visits the scope of the enclosing class after examining the scope of the nested class.
When you refer to x within Test1::Test2::m() in your example, the compiler is going to go up the scope chain and find the first x to be Test1::x. Because this isn't a static member variable you're getting the error.
If you want to refer to the global x use ::x. I modified your example to demonstrate:
#include <stdio.h>
int x = 0;
class Test1{
public:
char *x;
class Test2{
public:
int m(){
return ::x++;
}
};
};
int main() {
printf("x = %d\n", x);
Test1::Test2 foo;
foo.m();
printf("x = %d\n", x);
return 0;
}
This prints:
x = 0
x = 1
$.02 note on style: If you reserve nested classes for simple data containers that only operate on themselves, as is a common best practice, you won't run into this issue.
I'm working on a project with a pre-made .hpp file with all the declarations and stuff.
A struct is declared in the private part of the class, along with some private members.
I need to create an array with the type of the struct in my .cpp file.
//.hpp
private:
struct foo
{
std::string a;
unsigned int b;
};
std::string* x;
unsigned int y;
//.cpp
unsigned int returny()
{
return y; // No errors
}
foo newArray[10]; // Compile time error; unknown type name
Why is it that I can return y, which is also private, but not make an array out of the struct foo?
How can I fix this? (I'm in an introductory C++ class... so hopefully there's a simple solution)
There are couple of issues.
You can't use a type that's defined in the private section of class like you are trying.
The nested type can be used by specifying the appropriate scope.
EnclosingClass::foo newArray[10];
But this will work only if foo is defined in the public section of EnclosingClass.
you should define the struct int the outside of the class like this
struct Foo
{
std::string a;
unsigned int b;
};
class A {
private:
Foo foo;
...
}
in a book i am reading to learn basic c++, there is this example:
#include <iostream>
using namespace std;
class Point {
private: // Data members (private)
int x, y;
public: // Member functions
void set(int new_x, int new_y);
int get_x();
int get_y();
};
void Point::set(int new_x, int new_y) {
x = new_x;
y = new_y;
}
int Point::get_x() {
return x;
}
int Point::get_y() {
return y;
}
My question is, is it not possible in c++ to include the definition of the member functions inside the class itself? The above seems quite messy. The book says to define a class member function you should use 'return_type class_name::function(){arguments}. But in C# you can just do it within the same class and it is less code. I haven't been able to find much about properties in c++. Thanks for help.
Although it is possible, it's not really recommended. Actually, the way it's done in your book isn't how it should be done either (and hopefully, later on in the book that will change!). The way you'll see it done 99% of the time (yes, I pulled that number out of my ass) is a class definition in a header file (.h extension) and the definitions in a source file (.cpp extension). The header file will be imported so to speak, into the source file via #include.
You can define the members within the class as such.
class Point {
private: // Data members (private)
int x, y;
public: // Member functions
void set(int new_x, int new_y) {
x = new_x;
y = new_y;
}
int get_x() { return x; }
int get_y() { return y; }
};
However, this isn't a popular style of coding in C++. Most C++ conventions suggest that you separate the implementations (definitions) from the interface (the declarations) in different files (definitions would go into Point.cpp, and declarations would go into Point.h), unless the definitions are very short (like accessors).
You can define functions in the class definition in C++. This will cause them to be inline implicitly but that shouldn't matter because compilers have flexibility in terms of actually inlining. Usually this isn't done because it will increase compile time due to larger amounts of code being processed and the canonical C++ way it to put the method definitions in a separate source file.
class Point
{
private: // Data members (private)
int x, y;
public: // Member functions
void set(int new_x, int new_y)
{ x = new_x; y = new_y; }
int get_x()
{ return x; }
int get_y()
{ return y; }
};
of course you can write
#include <iostream>
using namespace std;
class Point {
private: // Data members (private)
int x, y;
public: // Member functions
void set(int new_x, int new_y)
{
x = new_x;
y = new_y;
}
int get_x()
{
return x;
}
int get_y()
{
return y;
}
};
But whole point is to separate declaration and implementation.
Yes we can Define a function inside a class.it has following advantage.
1)the function which you define inside a class is treated as an "inline" function .
(inline keyword before any function suggest compiler to place body of the definition of the function to where ever that function is been called from at compile time)
2)due to which inline function execute Faster.then normal function.
(remember its totally up to the compiler to make that function inline or not.you cannot force compiler to make it inline)
Most answers point out that it is possible but not recommended, I do not agree with the latter. For simple one-liner accessors it just makes sense to provide them inside the class definition in most cases:
class point {
int x,y;
public:
// ...
int posX() const { return x; }
int posY() const { return y; }
};
As of the setters, it will depend on whether you want to verify any invariant or not. In the former case, you might want to move it to a single translation unit, but even there if the checks are small I would just inline them inside the class definition.
The recommendations for separating declaration and definition of the member methods include things like:
smaller compile time: false, the compiler can parse the accessor trivially, it will not add much more to the parsing
smaller code size: false, if the function is not inlined, then the compiler must generate code for the function call, including calculation of the this pointer and actually perform the call. The inlined accessor will just require the reading of the member which will take less code.
higher compile time coupling: any change in the implementation of the function will require recompilation of all translation units that include the header... True, if you change the function, which for such a simple accessor will not happen.
I am reading "Local Classes" concept in Object-oriented programming with C++ By Balagurusamy (http://highered.mcgraw-hill.com/sites/0070593620/information_center_view0/).
The last line says "Enclosing function cannot access the private members of a local class. However, we can achieve this by declaring the enclosing function as a friend."
Now I am wondering how the highlighted part can be done?
Here is the code I was trying but no luck,
#include<iostream>
using namespace std;
class abc;
int pqr(abc t)
{
class abc
{
int x;
public:
int xyz()
{
return x=4;
}
friend int pqr(abc);
};
t.xyz();
return t.x;
}
int main()
{
abc t;
cout<<"Return "<<pqr(t)<<endl;
}
I know the code looks erroneous, any help would be appreciable.
Your friend statement is fine.
int pqr() {
class abc {
int x;
public:
abc() : x(4) { }
friend int pqr();
};
return abc().x;
}
int main() {
cout << "Return " << pqr() << endl;
}
Edit:
IBM offers this explanation for the issue raised in the comments:
If you declare a friend in a local class, and the friend's name is unqualified, the compiler will look for the name only within the innermost enclosing nonclass scope. [...] You do not have to do so with classes.
void a();
void f() {
class A {
// error: friend declaration 'void a()' in local class without prior decl...
friend void a();
};
}
friend void a(): This statement does not consider function a() declared in namespace scope. Since function a() has not been declared in the scope of f(), the compiler would not allow this statement.
Source: IBM - Friend scope (C++ only)
So, you're out of luck. Balagurusamy's tip only works for MSVC and similar compilers. You could try handing off execution to a static method inside your local class as a work-around:
int pqr() {
class abc {
int x;
public:
abc() : x(4) { }
static int pqr() {
return abc().x;
}
};
return abc::pqr();
}
There seems to be a misunderstand about local classes.
Normally there are here to help you within the function... and should NOT escape the function's scope.
Therefore, it is not possible for a function to take as an argument its own local class, the class simply isn't visible from the outside.
Also note that a variety of compilers do not (unfortunately) support these local classes as template parameters (gcc 3.4 for example), which actually prevents their use as predicates in STL algorithms.
Example of use:
int pqr()
{
class foo
{
friend int pqr();
int x;
foo(): x() {}
};
return foo().x;
}
I must admit though that I don't use this much, given the restricted scope I usually use struct instead of class, which means that I don't have to worry about friending ;)
I have no solution for the friend thing yet (don't even know if it can be done), but read this and this to find out some more about local classes. This will tell you that you cannot use local classes outside the function they are defined in (as #In silico points out in his answer.)
EDIT It doesn't seem possible, as this article explains:
The name of a function first introduced in a friend declaration is in the scope of the first nonclass scope that contains the enclosing class.
In other words, local classes can only befriend a function if it was declared within their enclosing function.
The friend int pqr(abc); declaration is fine. It doesn't work because the abc type has not been defined before you used it as a parameter type in the pqr() function. Define it before the function:
#include<iostream>
// By the way, "using namespace std" can cause ambiguities.
// See http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5
using namespace std;
// Class defined outside the pqr() function.
class abc
{
int x;
public:
int xyz()
{
return x=4;
}
friend int pqr(abc);
};
// At this point, the compiler knows what abc is.
int pqr(abc t)
{
t.xyz();
return t.x;
}
int main()
{
abc t;
cout<<"Return "<<pqr(t)<<endl;
}
I know you want to use a local class, but what you have set up will not work. Local classes is visible only inside the function it is defined in. If you want to use an instance of abc outside the pqr() function, you have to define the abc class outside the function.
However, if you know that the abc class will be used only within the pqr() function, then a local class can be used. But you do need to fix the friend declaration a little bit in this case.
#include<iostream>
// By the way, "using namespace std" can cause ambiguities.
// See http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5
using namespace std;
// pqr() function defined at global scope
int pqr()
{
// This class visible only within the pqr() function,
// because it is a local class.
class abc
{
int x;
public:
int xyz()
{
return x=4;
}
// Refer to the pqr() function defined at global scope
friend int ::pqr(); // <-- Note :: operator
} t;
t.xyz();
return t.x;
}
int main()
{
cout<<"Return "<<pqr()<<endl;
}
This compiles without warnings on Visual C++ (version 15.00.30729.01 of the compiler).
I am trying to declare and use a class B inside of a class A
and define B outside A.
I know for a fact that this is possible because Bjarne Stroustrup
uses this in his book "The C++ programming language"
(page 293,for example the String and Srep classes).
So this is my minimal piece of code that causes problems
class A{
struct B; // forward declaration
B* c;
A() { c->i; }
};
struct A::B {
/*
* we define struct B like this becuase it
* was first declared in the namespace A
*/
int i;
};
int main() {
}
This code gives the following compilation errors in g++ :
tst.cpp: In constructor ‘A::A()’:
tst.cpp:5: error: invalid use of undefined type ‘struct A::B’
tst.cpp:3: error: forward declaration of ‘struct A::B’
I tried to look at the C++ Faq and the closeset I got was here and here but
those don't apply to my situation.
I also read this from here but it's not solving my problem.
Both gcc and MSVC 2005 give compiler errors on this
The expression c->i dereferences the pointer to struct A::B so a full definition must be visible at this point in the program.
The simplest fix is to make the constructor of A non-inline and provide a body for it after the defintion of struct A::B.
Define the constructor for A AFTER the definition of struct B.
This is a good example of why you want to keep definitions separate from declarations. You need to change the order of things so that the constructor A::A() is defined after the definition of struct A::B.
class A
{
struct B;
B* c;
A();
};
struct A::B
{
int i;
};
A::A() { c->i; }
int main()
{
return 0;
}
Interestingly, I've bumped into the same problem with the page 293 ('11.12 A String Class') mentioned in the Stroustrup book.
The example provided in the printed book seems to be at fault, providing the following methods as inline, instead of defining them after the definition of struct Srep
class String {
// ...
void check(int i) const { if (i<0 || rep->sz <=i) throw Range(); }
char read(int i) const { return rep->s[i]; }
void write(int i, char c) { rep=rep->get_own_copy(); rep->s[i]=c; }
...etc...
I googled a bit, and found the author's latest implementation of this String Class, available here:
http://www2.research.att.com/~bs/string_example.c
He seems to have modified it so that these methods are no longer inline, to avoid the problem mentioned in this thread.