Suppose I have nested classes as follows defined in a header file:
class ClassA
{
private:
class ClassB
{
private:
int member_b;
public:
void function_name();
};
};
In order to give a definition to the function "function_name()" in an external .cpp file, I have to access it like this:
void ClassA::ClassB::function_name()
{
std::cout << member_b;
return;
}
For the sake of this example, please do not ask why I'm using nested classes; I have a reason for doing so in my actual project. However, my question is this; is it possible to somehow shorten the ClassA::ClassB::function_name() in the implementation file to something like short::function_name() while still keeping the classes nested? I don't think that typedefs or new namespace definitions can help me here, but maybe I'm wrong.
Qualified type names allow you to define a typedef to represent a qualified class name. You can then use the typedef with the :: (scope resolution) operator to refer to a nested class or class member, as shown in the following example:
class outside
{
public:
class nested
{
public:
static int x;
static int y;
int f();
int g();
};
};
int outside::nested::x = 5;
int outside::nested::f() { return 0; };
typedef outside::nested outnest; // define a typedef
int outnest::y = 10; // use typedef with ::
int outnest::g() { return 0; };
However, using a typedef to represent a nested class name hides information and may make the code harder to understand.
Source : https://www.ibm.com/support/knowledgecenter/en/SSPSQF_9.0.0/com.ibm.xlcpp111.aix.doc/language_ref/cplr061.html
Have you tried using aliases?
// C++11
using fmtfl = std::ios_base::fmtflags;
// C++03 equivalent:
// typedef std::ios_base::fmtflags fmtfl;
fmtfl fl_orig = std::cout.flags();
fmtfl fl_hex = (fl_orig & ~std::cout.basefield) | std::cout.showbase | std::cout.hex;
// ...
std::cout.flags(fl_hex);
Code source: https://msdn.microsoft.com/en-us/library/dn467695.aspx
Related
I have a struct defined in an anonymous namespace. Then I also want to have a class defined which has a field of that struct type.
I forward declare the struct in the header file:
struct my_str;
class my_class {
public:
struct my_str *field;
void method();
};
and then in the cpp file I have the actual type defined and some methods using it:
namespace {
struct my_str {
int data;
};
}
void helper(struct my_str * obj) {
std::cout << obj->data;
}
void my_class::method() {
helper(field);
}
This doesn't compile:
test.cc:10:20: error: reference to ‘my_str’ is ambiguous
It lists 2 definitions for my_str, the forward declaration and the one from the anonymous namespace.
Is there a way to disambiguate and make this compile?
An anonymous namespace hides the name from the outside, so you can't use that - there is no way for an outsider to refer to that type.
You don't need to write the definition in an anonymous namespace - it is hidden outside anyway.
However, this will lead to undefined behaviour if you have another global type with the same name, due to the One Definition Rule.
Probably the best solution is to hide the definition inside my_class instead:
Header:
class my_class {
public:
// Note the separate declaration; a one-liner would declare
// that there is a global `my_str`.
struct my_str; // Not defined for the outside world, but the name is accessible.
my_str *field;
void method();
};
Source:
struct my_class::my_str
{
int data;
};
namespace
{
void helper(my_data::my_str* obj) {
std::cout << obj->data;
}
}
void my_class::method() {
helper(field);
}
I came up with this approach and would like to hear what people think.
"every problem in computer science can be solved by adding another level of indirection"
.h:
struct my_str_wrap;
class my_class {
public:
struct my_str_wrap* field;
void method();
};
.cc:
namespace {
struct my_str {
int data;
};
}
struct my_str_wrap {
struct my_str w;
};
void helper(struct my_str& obj) {
std::cout << obj.data;
}
void my_class::method() {
helper(field->w);
}
When and why should we use the 'struct' keyword when declaring a class pointer variable in C++?
I've seen this in embedded environments so I suspect that this is some kind of hold over from C. I've seen plenty of explanations on when to use the 'struct' keyword when declaring a struct object as it relates to namespaces in C (here), but I wasn't able to find anyone talking about why one might use it when declaring a class pointer variable.
Example, in CFoo.h:
class CFoo
{
public:
int doStuff();
};
inline Foo::doStuff()
{
return 7;
}
And later in a different class:
void CBar::interesting()
{
struct CFoo *pCFoo;
// Go on to do something interesting with pCFoo...
}
There's rarely a reason to do this: it's a fallover from C and in this case the programmer is simply being sentimental - perhaps it's there as a quest for readability. That said, it can be used in place of forward declarations.
In some instances you might need to disambiguate, but that's not the case here. One example where disambiguation would be necessary is
class foo{};
int main()
{
int foo;
class foo* pf1;
struct foo* pf2;
}
Note that you can use class and struct interchangeably. You can use typename too which can be important when working with templates. The following is valid C++:
class foo{};
int main()
{
class foo* pf1;
struct foo* pf2;
typename foo* pf3;
}
There are two reasons to do this.
The first one is if we are going to introduce a new type in the scope using an elaborated name. That is in this definition
void CBar::interesting()
{
struct CFoo *pCFoo;
// Go on to do something interesting with pCFoo...
}
the new type struct CFoo is introduced in the scope provided that it is not yet declared. The pointer may point to an incomplete type because pointers themselves are complete types.
The second one is when a name of a class is hidden by a declaration of a function or a variable. In this case we again need to use an elaborated type name.
Here are some examples
#include <iostream>
void CFoo( const class CFoo * c ) { std::cout << ( const void * )c << '\n'; }
class CFoo
{
public:
int doStuff();
};
int main()
{
class CFoo c1;
return 0;
}
Or
#include <iostream>
class CFoo
{
public:
int doStuff();
};
void CFoo( void ) { std::cout << "I am hidding the class CGoo!\n"; }
int main()
{
class CFoo c1;
return 0;
}
In C, two different styles are the most common:
typedef struct { ... } s; with variables declared as s name;.
struct s { ... }; with variables declared as struct s name;
In C++ you don't need to typedef to omit the struct keyword, so the former style is far more in line with the C++ type system and classes, making it the most common style in C++.
But then there are not many cases in C++ when you actually want to use struct instead of class in the first place - structs are essentially classes with all members public by default.
The reason for this may be as simple as not having to include a header file whose contents aren't needed other than for announcing that CFoo names a type. That's often done with a forward declaration:
class CFoo;
void f(CFoo*);
but it can also be done on the fly:
void f(struct CFoo*);
In MyClass below, enum MyType is defined inside the class.
In main, I create a variable of MyClass::MyType t. This compiles fine. However, when I wish to assign it a value such as OPEN, there is a compilation error "OPEN was not declared in this scope"
Firstly it probably doesn't make sense declaring an enum type inside the class and limiting its scope there and then creating a variable of that enum type elsewhere, but I'm just trying to understand what's happening.
In the first place, how am I able to create a variable of MyType in main when an object hasn't even been created? Are enums and struct types defined in a class like that implicitly static?
Also, the compiler has access to the enum code, so why doesn't it understand "OPEN"? Thanks
#include <iostream>
using namespace std;
class MyClass
{
public:
enum MyType
{
OPEN,
CLOSED
};
struct MyStruct
{
int val1;
int val2;
};
};
int main()
{
MyClass::MyType t;
t = OPEN; // compilation error
return 0;
}
Your enum MyType is inside the class, so its values are expected to be accessed through the class and the enumeration. You are already creating a MyType without instantiating the class, but an example of instantiation through the class is also provided.
class MyClass
{
public:
enum MyType
{
OPEN,
CLOSED
};
struct MyStruct
{
int val1;
int val2;
};
};
int main()
{
MyClass::MyType t; // Already a MyType value!
MyClass c; // Building your class
t = MyClass::MyType::OPEN; // No compilation error
t = c.OPEN; // Accessing enum through instantiated class
return 0;
}
Like Remy said. Value OPEN is a part of MyClass class and is only reachable in that classes scope. For your compiler to see it and use it you need to acces it through MyClass::OPEN.
(In addition to what others wrote)
If supported by the compiler (Since C++ 11),
it is a better practice to use enum class:
enum class MyType
{
OPEN,
CLOSED
};
"The enum classes (“new enums”, “strong enums”) address three problems with traditional C++ enumerations:
1) Conventional enums implicitly convert to an integer, causing errors when someone does not want an enumeration to act as an integer.
2) Conventional enums export their enumerators to the surrounding scope, causing name clashes.
3) The underlying type of an enum cannot be specified, causing confusion, compatibility problems, and makes forward declaration impossible."
ISOCPP FAQ - enum class
-
In that case, use the syntax:
int main()
{
MyClass c;
MyClass::MyType t;
t = MyClass::MyType::OPEN;
return 0;
}
See [decl.enum]/11:
Each enum-name and each unscoped enumerator is declared in the scope
that immediately contains the enum-specifier. Each scoped enumerator
is declared in the scope of the enumeration. These names obey the
scope rules defined for all names in [basic.scope] and [basic.lookup].
[ Example:
enum direction { left='l', right='r' };
void g() {
direction d; // OK
d = left; // OK
d = direction::right; // OK
}
enum class altitude { high='h', low='l' };
void h() {
altitude a; // OK
a = high; // error: high not in scope
a = altitude::low; // OK
}
— end example ] An enumerator declared in class scope can be referred
to using the class member access operators (::, . (dot) and ->
(arrow)), see [expr.ref]. [ Example:
struct X {
enum direction { left='l', right='r' };
int f(int i) { return i==left ? 0 : i==right ? 1 : 2; }
};
void g(X* p) {
direction d; // error: direction not in scope
int i;
i = p->f(left); // error: left not in scope
i = p->f(X::right); // OK
i = p->f(p->left); // OK
// ...
}
— end example ]
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;
...
}
I would like to be able to achieve something like this:
class Zot
{
namespace A
{
static int x;
static int y;
}
}
I am working with a legacy system that uses code generation heavily off a DB schema, and certain fields are exposed as methods/variables in the class definition. I need to add a few extra static variables to these classes and would like to guarantee no clashes with the existing names.
The best I have come up with is to use another struct to wrap the statics as if it were a namespace:
class Zot
{
struct A
{
static int x;
static int y;
}
}
Is there a better way?
Update:
An extra requirement is to be able to access these from a template elsewhere
e.g.
template<class T>
class B
{
void foo() { return T::A::x; }
};
So putting them in a separate class won't work
Really the inner struct is your best bet. Another possibility would be to use a typedef to bring in a class of statics. This works well for code generation in that you can separate the extras from the generated code:
In the generated file that doesn't care at all what's in Zot_statics:
class Zot_statics;
class Zot
{
public:
typedef Zot_statics A;
int x; // This is ok
};
In a hand-maintained header for when you need to access x and y:
class Zot_statics
{
public:
static int x;
static int y;
};
In a hand-maintained cpp file:
int Zot_statics::x;
int Zot_statics::y;
And your template should work just fine with Zot::X referring to the instance variable X on Zot, and Zot::A::x refering to the static variable.