I've been running across this snippet of code and after execution I found out that everything compiles and executes fine (the int code member of the derived class is set to 65). However I was wondering how would one be able to access the char code member of the derived class?
#include <iostream>
using namespace std;
class base {
public:
base() : code('B') { }
char code;
};
class derived : public base
{
public:
int code;
};
int main(void)
{
derived d;
d.code = 65;
std::cout << d.code;
};
By specifying the correct scope for the base member variable using a qualified name lookup, as follows:
d.base::code = 'x'
std::cout << d.base::code << '\n';
See this section on qualified name lookups for more details.
Related
I am trying to understand a c++ program listed here. I am confused about the second use of double colons on lines 86-87:
using TransformType = itk::AffineTransform< ScalarType, Dimension >;
TransformType::Pointer transform = TransformType::New();
It looks like TransformType is a user-defined type. How would one use it before New()? I heard that the double-colon is to be used following a namespace, but here, TransformType is a type (namely class) rather than a namespace. Can someone clarify --- should double colon be always used after a namespace in C++? Would it possible to use a dot (like in Java) instead?
You use the scope resolution operator (::) to name something in a namespace, or in a class, or in a scoped enum; this is called qualified lookup.
#include <iostream>
namespace N
{
int x = 0;
}
int main()
{
std::cout << N::x << '\n';
}
Using it with a class usually means you're referring to some static member, because otherwise you'd generally be using objectInstance.member instead.
#include <iostream>
class C
{
public:
static int x;
}
int C::x = 0;
int main()
{
std::cout << C::x << '\n';
}
Though, within a non-static member function, there are still uses for ::, such as disambiguating between names that exist concurrently in different bases.
class Base
{
public:
void foo() {}
};
class Derived : public Base
{
public:
void foo()
{
// Do base version (omitting Base:: will just call this one again!)
Base::foo();
// Now maybe do other things too
}
};
int main()
{
Derived obj;
obj.foo();
}
… or for naming a non-static member in a scenario where an object context is not required:
#include <iostream>
class C
{
public:
int x;
}
int main()
{
std::cout << sizeof(C::x) << '\n';
decltype(C::x) y = 42;
}
It's needed with scoped enums because, well, they're scoped; that's the whole point of them. They don't leak into the surrounding scope but have their own which as a result you need to specify specifically.
enum class E
{
Alpha,
Bravo,
Charlie
};
void foo(E value) {}
int main()
{
foo(E::Alpha);
}
Some languages let you access static members of classes with the type name followed by ., just like you'd access non-static members of classes with the object name followed by .. C++ is not one of those languages.
By the way, this is legal:
#include <iostream>
class C
{
public:
int x = 42;
};
int main()
{
C obj;
std::cout << obj.C::x << '\n';
// ^^^ what?!
}
Adding scope resolution to x here is not necessary, because the language already knows from the obj. that you're asking for a member of a class C. But you can still add it if you want. It's just usually "done for you" in this case.
In the following complete program:
#include <vector>
class Derived : private std::vector<int> {
public:
void f();
};
void Derived::f() {
Derived d;
d.std::vector<int>::push_back(0);
}
int main() {
Derived d;
d.f();
}
the line
d.std::vector<int>::push_back(0);
can be replaced by
d.vector<int>::push_back(0);
and the compilation would complete w/o warning both in gcc 7 and clang 6.
I don't understand why the std:: part of the scope resolution is optional, since there's no using namespace std declaration.
As others already mentioned:
Do not inherit from STL!
See this and this and read Effective c++ book.
Apart from the derivation from STL, it could be an everyday problem. I think you are searching for how qualified name lookup works.
Consider the following code
#include <iostream>
#include <string>
namespace myNamespace {
namespace nested {
class base {
protected:
std::string print() { return "Fantastic"; };
static const int four= 4;
};
}
}
class derived : private myNamespace::nested::base
{
public:
// no need to extra qualify base class methods, since derived access the scope of the base class
std::string doStuff() { return print() + std::to_string(four); };
};
int main()
{
derived d;
std::cout << d.doStuff();
}
It has the same structure, deriving from something that is a part of a namespace. As you noticed, in the derived there is no need to extra qualify the print method. However, the following is completely legal call in the doStuff method:
print();
base::print();
myNamespace::nested::base::print();
Note that simply nested::base::print(); is not legal - myNamespace should be used.
Ps. I compiled with MSVC 143, and always produced this output:
Fantastic4
I have the declaration of class Ainside a third party library, so I can't modify it.
I need to use the declaration of class B to pass it to a method, is there a way to do it without modifying class A?
When I try this:
#include <iostream>
using namespace std;
class A
{
public:
union {
class B
{
public:
int x;
};
}un;
};
void foo(A::B & test)
{
}
int main() {
A::B test;
test.x=10;
cout << test.x << endl;
return 0;
}
I get the error:
error: B is not a member of A
Live Example!
My assumption is that it happens because B is in a unnamed namespace.
PS: If I could modify the declaration of the union
from:
union {...
to:
union T {...
This will be done simple by:
A::T::B test;
You can get the type of the union using decltype, then you can access B:
decltype(std::declval<A&>().un)::B test;
coliru example
class Example{
public:
friend void Clone::f(Example);
Example(){
x = 10;
}
private:
int x;
};
class Clone{
public:
void f(Example ex){
std::cout << ex.x;
}
};
When I write f as a normal function, the program compiles successful. However, when I write f as a class member, this error occurs.
Screenshot:
The error you're seeing is not a root-cause compilation error. It is an artifact of a different problem. You're friending to a member function of a class the compiler has no earthly clue even exists yet,much less exists with that specific member.
A friend declaration of a non-member function has the advantage where it also acts as a prototype declaration. Such is not the case for a member function. The compiler must know that (a) the class exists, and (b) the member exists.
Compiling your original code (I use clang++ v3.6), the following errors are actually reported:
main.cpp:6:17: Use of undeclared identifier 'Clone'
main.cpp:17:25: 'x' is a private member of 'Example'
The former is a direct cause of the latter. But doing this instead:
#include <iostream>
#include <string>
class Example;
class Clone
{
public:
void f(Example);
};
class Example
{
public:
friend void Clone::f(Example);
Example()
{
x = 10;
}
private:
int x;
};
void Clone::f(Example ex)
{
std::cout << ex.x;
};
int main()
{
Clone c;
Example e;
c.f(e);
}
Output
10
This does the following:
Forward declares Example
Declares Clone, but does not implement Clone::f (yet)
Declares Example, thereby making x known to the compiler.
Friends Clone::f to Example
Implements Clone::f
At each stage we provide what the compiler needs to continue on.
Best of luck.
How do I initialize the structure variables of type class objects? I have the following code:
#include<iostream>
using namespace std;
class bitmap {
public :
bitmap() { clear() ;}
get();
set();
clear();
static const int a=10;
};
bitmap::get() {
};
struct bitmap_list {
bitmap_list_value _value;
}
int main()
{
bitmap bitmap_list_value;
bitmap_list bbbb;
bbbb. _value=bitmap_list_value.a;
cout << bbbb._value << endl;
}
Is this code correct, or is it possible to initialize the structure containing the class objects? This is the error I receive:
>error: ‘struct error: ‘_bitmap_list_value’ does not name a type
>error:bitmap_list’ has no member named ‘_value’
No, this code is not correct. You're referencing a type bitmap_list_value which is never declared.
Based on your comment ("bitmap_list_value is object of class bitmap"), it sounds as if you also have this, but haven't included it in your question's code for some reason:
typedef bitmap bitmap_list_value;
But yes, of course you can include members of class types inside structs. A struct is more or less a class with all fields made public by default, you can define methods inside structs just as you can with classes, and so on.