How do I make G::t static? (e.g., G::t should be of type const static int&) G::t is defined by the constructor parameter p and not available anywhere else.
class G {
public:
// I want to make this static.
const int& t;
G(const int& p);
};
G::G(const int& p) : t(p) {}
int main() {
int a=2;
const int& b = a;
G g = G(b);
}
e.g.:
const int a = 10;
class foo
{
static const constexpr int& t = a;
};
You can't initialize static member in constructor, because constructors are for objects, not for class as whole.
Why are you even using a constructor if you want to set static members to be used by static functions? That's not what constructors are for. You definitely can't initialize a static member in an initializer-list, because that would mean it got initialized every time you constructed another object. (Just think about the difference between per-class static data and per-instance data and it should be obvious why the question makes no sense).
You could use a static local, which is initialized on first use so can be initialized at run-time, and then can be accessed by the static member functions:
class G {
public:
static int t(const int& p = 0, bool set = false);
G(const int& p);
};
G::G(const int& p) { t(p, true); }
int G::t(const int& p, bool set)
{
static bool is_set = false;
if (!is_set)
{
if (!set)
throw std::logic_error("Cannot use G::t before it is set");
}
else if (set)
throw std::logic_error("Cannot set G::t more than once");
static const int tt = p;
set = true;
return tt;
}
int main() {
int a=2;
const int& b = a;
G g = G(b);
int t = G::t();
}
But this is a horrible hack, you should think carefully about your design and whether using a constructor is appropriate here, or even if using a class is appropriate.
The member initializer list can only be used to initialize instance variables, so if t is static, you can only reassign it in the constructor body.
And because references can't be reassigned, you have to use a pointer. A reference_wrapper doesn't work because it would need to be statically initialized (unless you have a global int that you can use for that).
E.g.
class G {
public:
static const int* t;
G(const int& p);
};
const int* G::t; // definition in .cpp
G::G(const int& p) {
t = &p;
}
Related
class Foo
{
public:
const int a;
const int* x;
int* const y;
Foo() : a{ 0 }, y{ new int(20) } {
x = new int(10);
}
};
int main()
{
Foo f;
// f.a = 100; // cannot
f.x = new int(100);
// f.y = new int(100); // cannot
}
When const int a is defined as fields of a class,
it is called a constant member. It must be initialized in the initializer list and cannot be changed afterwards.
How about const int* x (which is the same as int const* x) and int* const y? Which one should be called as a constant member? If "constant member" is defined as field that must be initialized in the initializer list and cannot be changed afterwards, then the constant member is y rather than x. Am I wrong here?
Edit
According to IntelliSense, y is a constant member.
OK. I am sure I am not wrong. I will delete this question shortly. Thank you for your participation!
The "const int* x" is a (non-const) pointer to a const int. Since x is non-const, it need not be initialized upon construction.
Here are some examples:
class C
{
public:
C() :
const_int(1),
const_int_again(2),
const_ptr_to_non_const_int(nullptr),
const_ptr_to_const_int(nullptr)
{}
private:
const int const_int;
int const const_int_again;
const int* ptr_to_const_int; // Doesn't need initialized
int const* ptr_to_const_int_again; // Doesn't need initialized
int* const const_ptr_to_non_const_int;
const int* const const_ptr_to_const_int;
int const* const const_ptr_to_const_int_again;
};
You may find the cdecl.org website helpful.
Is there a nice way to have a non static value as default argument in a function? I've seen some older responses to the same question which always end up in explicitly writing out the overload. Is this still necessary in C++17?
What I'd like to do is do something akin to
class C {
const int N; //Initialized in constructor
void foo(int x = this->N){
//do something
}
}
instead of having to write
class C {
const int N; //Initialized in constructor
void foo(){
foo(N);
}
void foo(int x){
//do something
}
}
which makes the purpose of the overload less obvious.
One relatively elegant way (in my opinion) would be to use std::optional to accept the argument, and if no argument was provided, use the default from the object:
class C {
const int N_; // Initialized in constructor
public:
C(int x) :N_(x) {}
void foo(std::optional<int> x = std::nullopt) {
std::cout << x.value_or(N_) << std::endl;
}
};
int main() {
C c(7);
c.foo();
c.foo(0);
}
You can find the full explanation of what works/doesn't work in section 11.3.6 of the standard. Subsection 9 describes member access (excerpt):
A non-static member shall not appear in a default argument unless it
appears as the id-expressionof a class member access expression
(8.5.1.5) or unless it is used to form a pointer to member
(8.5.2.1).[Example:The declaration of X::mem1()in the following example
is ill-formed because no object is supplied for the non-static
memberX::a used as an initializer.
int b;
class X {
int a;
int mem1(int i = a);// error: non-static memberaused as default argument
int mem2(int i = b);// OK; useX::b
static int b;
};
We have a structure that accepts C function pointers:
int one(int x)
{
}
int two(int x)
{
}
struct Cstruct
{
int (*fn1)(int);
int (*fn2)(int);
};
Now I have a C++ class that has below methods:
class A
{
public:
int one(int x)
{
}
int two(int x)
{
}
int three(int x)
{
struct Cstruct cstr = {&this->one, &this->two};
}
};
While trying to initialize class A methods address to a instance of Cstruct compiler is giving error of an invalid conversion?
How can I assign the Class member function address to Cstruct?
You cannot do it, because C++ pointer to a non-static member function is not compatible with a non-member function pointer type. This is because member functions require an additional argument - the object on which the member function needs to be called, which becomes this pointer inside the invocation.
If you make your member functions static, your code would compile. However, it would not necessarily do what you want to achieve, because one and two have no access to other non-static members of A.
A trick to passing member functions to C functions requires passing an additional void* pointer with the "registration" record, and having C code pass it back to your static callback functions:
struct Cstruct
{
void *context; // Add this field
int (*fn1)(void*, int);
int (*fn2)(void*, int);
};
class A
{
public:
static int oneWrap(void* ptr, int x)
{
return static_cast<A*>(ptr)->one(x);
}
static int twoWrap(void* ptr, int x)
{
return static_cast<A*>(ptr)->two(x);
}
int one(int x)
{
}
int two(int x)
{
}
int three(int x)
{
struct Cstruct cstr = {this, &this->oneWrap, &this->twoWrap};
}
};
C code would need to pass the value of context to fn1 and fn2:
cs.fn1(cs.context, 123);
cs.fn2(cs.context, 456);
I have the following code:
class A
{
int x;
public:
A(int i=25) { x=i; }
int& f() const { return x; }
};
int main()
{
A a(15);
cout<<a.f();
return 0;
}
I get an error saying that I can't initialize a reference of type int& from an expression of type const int? If I modify function's f() header, like "int f() const" or like "int& f()" it works. I know that a const function can't modify the members of the class, but in my example that's not happening and still is something wrong I can't understand.
Secondly, I have this piece of code:
class B { /* instructions */ };
class D1: virtual B { /* instructions */ };
class D2: virtual B { /* instructions */ };
class D3: B { /* instructions */ };
class D4: private B { /* instructions */ };
class D5: virtual public B { /* instructions */ };
class M1: D1, public D2, D3, private D4, virtual D5
{ /* instructions */ };
class M2: D1, D2, virtual D3, virtual D4, virtual D5
{ /* instructions */ };
The question is how many times is B inherited in M1 and and in M2. I think the answer is 3 (first from D1, then from D3 and then from D4) for both, but I'm not sure. Am I right?
You're returning a reference to a member of your class. However, since you method is const, you're not allowed to return a non-const reference, because this would allow for the end user to modify your class state, after calling a const method.
Consider this:
class A
{
int x;
public:
A(int i=25) { x=i; }
const int& f() const { return x; }
};
int main()
{
A a(15);
int &ref = const_cast<int &>(a.f());
ref = 42;
// a.x == 42
return 0;
}
Using const_cast is generally a bad idea, it's here to demonstrate what could happen if you were allowed to return a non-const reference from a const method.
The end user could change the property x from your class, because of a call to a const function, which is not supposed to happen.
Returning the result by value is imo the way to go, since it's just an integer.
First, your function may not be modifying a const value, but you're trying to return a const value as a non-const, which could then be modified. The compiler is protecting you. To keep it const, modify it as:
const int &f() const {... }
or
int f() const { .... }
The first returns a const reference, the second returns the result by-value.
In a non-static const member function, the type of this is changed to A const *const. Therefore it follows that the type of x is changed to int const&. A const object cannot be implicitly-converted to a non-const version of its type.
For your first question:
class A
{
int x;
public:
A(int i=25) { x=i; }
const int& f() const { return x; }
//^^You should add const here
};
int main()
{
A a(15);
cout<<a.f();
return 0;
}
Otherwise, you are returning non-const reference from a const member function. Another option is to simply return by value.
const int& f() const is the way.
You're right, 3 times for both.
I have two questions about the following code.
class cls{
int vi;
public:
cls(int v=37) { vi=v; }
friend int& f(cls);
};
int& f(cls c) { return c.vi; }
int main(){
const cls d(15);
f(d)=8;
cout<<f(d);
return 0;
}
Why does it compile, since f(d) = 8 attemps to modify a const object?
Why does it still print 15, even after removing the const attribute?
It is not modifying a const object as a copy of d is being made due to the argument of f() being passed by value and not by reference. This is also the reason that d is unchanged as it is not being modified.