For a constructor with multiple arguments...
For example:
class C {
public:
C(int a=1, int b=2){ cout << a << ", " << b << "\n"; }
}
int main(){
C a(10), b = 20;
}
output:
10, 2
20, 2
How do I just assign value to the 2nd parameter? So that I can get "1, 20" without knowing the default values? Or is that that I must always assign value to the argument that precedes before I can use the arguments behind?
And how do I implicitly assign all the parameters? If I can't do that, why? For the above example (as I am new to C++), I once thought I would get "10, 20" as output instead.
Or is that that I must always assign value to the argument that precedes before I can use the arguments behind?
Yes. Otherwise, how is the compiler supposed to know which argument should be used for which parameter?
However, there are ways to accomplish this. For example,
struct C {
enum { DefaultA = 1, DefaultB = 2 };
C(int a = DefaultA, int b = DefaultB) { /* ... */ }
};
C object(C::DefaultA, 20);
Or, if you have a lot of parameters with different "defaults:"
struct CParams {
int a, b;
CParams() : a(1), b(2) { }
};
struct C {
C(CParams x) { /* ... */ }
};
CParams params;
params.b = 20;
C object(params);
C++ doesn't support named arguments. You have to specify the first one.
Also, the variable name b from the main function is completely separate from the b in the constructor definition. There's no relationship whatsoever implied by the naming.
I had the same thought (Convienient C++ struct initialisation -- perhaps you find something you like better there) some time ago, but just now, reading your question, I thought of a way to actually accomplish this. But it is quite some extra code, so the question remains if it is actually worth it. I just implemented it very sketchy and I am not proud of my choice of names (I usually don't use _ but it's late). Anyway, this is how you can do it:
#include <iostream>
struct C_members {
int a;
int b;
C_members(int _a, int _b) : a(_a), b(_b) {}
};
class C_init {
public:
virtual C_members get(C_members init) const {
return init;
}
};
class C_a : public C_init {
private:
int a;
public:
C_a(int _a) : a(_a) {}
C_members get(C_members init) const {
init.a = a;
return init;
}
};
class C_b : public C_init {
private:
int b;
public:
C_b(int _b) : b(_b) {}
C_members get(C_members init) const {
init.b = b;
return init;
}
};
class C : private C_members {
private:
static const C_members def;
public:
C(C_init const& ai = C_init(), C_init const& bi = C_init()) : C_members(ai.get(bi.get(def)).a, bi.get(ai.get(def)).b) {
std::cout << a << "," << b << std::endl;
}
};
const C_members C::def(1,2); // default values
// usage:
int main() {
C c1(C_b(77)); // 1,77
C c2(C_a(12)); // 12,2
C c3(C_b(5),C_a(6)); // 6,5
return 0;
}
There is a lot of stuff that can be improved (with templates (for code reduction) and with const refs in the get method), but you get the idea.
As a bonus feature, you almost have the pimpl idiom implemented (very little effort is necessary to extend this to an actual pimpl design).
Usually in OOP, every object instance holds (and represents) a state.
So the best way is to define an accessor functions such as
void setB(int newBvalue);
and also to hold b as a private member.
if "b" is shared among all the instances of the same object, consider to save a static variable.
Related
I am using C++ 14 with clang on MacOS Sierra. I want to enforce a rule by design. Following is the rule.
I have a member variable in my class say:
unsigned int m_important_num;
There are 4 methods in my class.
fun1();
fun2();
fun3();
fun4();
Objective:
I want only fun2() to be able to change the value of m_important_num.
Question:
Is it possible to make it compiler error if any method other than fun2() changes the variable?
One possible way is to declare it const somehow empower fun2() to change const variables? Is this a good solution? Or are their any better solutions?
Secondary question:
Is it a wrong design to try do such a thing?
Sort of, with additional layer:
class S1 {
public:
void fun2() { /*Modify m_important_num */ }
unsigned int getImportantNum() const { return m_important_num;}
private:
unsigned int m_important_num;
};
class S2 : private S1
{
public:
void fun1();
using S1::fun2; // or void fun2() {S1::fun2();}
void fun3();
void fun4();
};
As Yakk commented, if func2 need access to S2 members, CRTP can solve that:
template <typename Derived>
class S1 {
public:
void fun2() { asDerived().foo3(); /*Modify m_important_num */ }
unsigned int getImportantNum() const { return m_important_num;}
private:
Derived& asDerived() { return stataic_cast<Derived&>(*this); }
private:
unsigned int m_important_num;
};
class S2 : private S1<S2>
{
// friend class S1<S2>; // If required.
public:
void fun1();
using S1::fun2; // or void fun2() {S1::fun2();}
void fun3();
void fun4();
};
Encapsulate it down. Put m_important_num in its own class. Aggregate it in your existing class. Have a getter for it. Then put fun2() as a member function of your inner class.
I little variant (if I understand correctly) of the Jeffrey solution: put the variable in an inner class and make it private; create a public getter and make func2() friend to the inner class.
I mean
struct foo
{
int f1 () { return b0.getVal(); }; // you can read `val` everywhere
void f2 () { b0.val = 42; }; // you can write `val` in f2()
void f3 () { /* b0.val = 42; ERROR ! */ }; // but only in f2()
class bar
{
private:
int val = 24;
public:
int getVal () { return val; }
friend void foo::f2 ();
};
bar b0;
};
In other words: friend is your friend.
If you want to prevent a method from modifying any member in the class you can use the trailing const identifier:
class something{
private:
unsigned int var;
public:
void fun1() const;
void fun2();
void fun3() const;
void fun4() const;
}
Here, only fun2() will be able to modify the variable.
I know there are lots of good answers, but there is also an option that you sort of alluded to in your question:
One possible way is to declare it const somehow empower fun2() to change const variables?
#include <iostream>
using uint = unsigned int;
class Test
{
const uint num;
public:
Test(uint _num)
:
num(_num)
{}
uint get_num() const
{
return num;
}
void can_change_num(uint _new_num)
{
uint& n(const_cast<uint&>(num));
n = _new_num;
}
void cant_change_num(uint _new_num)
{
// num = _new_num; // Doesn't compile
}
};
int main()
{
Test t(1);
std::cout << "Num is " << t.get_num() << "\n";
t.can_change_num(10);
std::cout << "Num is " << t.get_num() << "\n";
return 0;
}
Produces
Num is 1
Num is 10
You already got lots of good answers to your primary question. I'll try to address the secondary one.
Is it a wrong design to try do such a thing?
It's hard to say w/o knowing more about your design. In general anything like this detected during a code review would raise a big red flag. Such a protection makes sense in a case of a big class with convoluted logic/implementation. Otherwise why would you like to go an extra mile and make your code much more complicated? The fact you seek for this can indicate your class became unmanageable.
I'd recommend to consider splitting it to smaller parts with better defined logic where you won't worry such mistakes can happen easily.
Im learning C++, and I am trying to do a little app. My app takes an informal ticket (without TAX) like this:
2
3 Mi_primera_tablet 7.95
1 El_general_en_su_laberinto Gabriel_García_Márquez 23.50
Where the first line is the number of items
In the second and third line= type of tax + title + price without TAX
The items can be of different types: books(TAX type 3), toys(TAX type 1)
All types inherit from the class article, but depending of the TAX type the price will be different (polymorphism).
I need to store all items (different types) in an array, how can I do it?
You can store pointers in the array.
Exapmle (c++11):
#include <iostream>
#include <vector>
#include <memory>
struct A {
int value;
};
struct B {
double item;
};
class Element {
public:
explicit Element(A a);
explicit Element(B b);
const A * AsA() const;
const B * AsB() const;
private:
class AbstractElement {
public:
virtual ~AbstractElement() {
}
protected:
AbstractElement() {
}
};
template <typename T>
struct ConcreteElement : public AbstractElement {
T body;
explicit ConcreteElement(T input_body)
: body(std::move(input_body)) {
}
};
std::unique_ptr<AbstractElement> element_;
};
Element::Element(A a)
: element_(new ConcreteElement<A>(a)) {
}
Element::Element(B b)
: element_(new ConcreteElement<B>(b)) {
}
const A * Element::AsA() const {
const auto concrete_element =
dynamic_cast<ConcreteElement<A> *>(element_.get());
return concrete_element ? &(concrete_element->body) : nullptr;
}
const B * Element::AsB() const {
const auto concrete_element =
dynamic_cast<ConcreteElement<B> *>(element_.get());
return concrete_element ? &(concrete_element->body) : nullptr;
}
int main() {
std::vector<Element> values;
values.push_back(Element(A{1}));
values.push_back(Element(B{1.5}));
values.push_back(Element(A{-5}));
values.push_back(Element(B{0}));
for (const auto & element : values) {
const auto p_a = element.AsA();
if (p_a) {
std::cout << "A: " << p_a->value << std::endl;
} else {
const auto p_b = element.AsB();
std::cout << "B: " << p_b->item << std::endl;
}
}
return 0;
}
output:
A: 1
B: 1.5
A: -5
B: 0
Maybe you can try boost::variant library, it act as a wrapper around anything. then you can store many boost::variant wrapper in an array
if I understood your question correctly, you need to know how to define an array of your base class with it's derived classes. If this is the case, you can do it by defining an array in the base class, which in your case would look something like this:
article ArrayName [n];
Books Books = new Books();
//do some thing with the books object
ArrayName[0] = Books;
All types inherit from the class article, but depending of the TAX
type the price will be different (polymorphism).
type or TAX type could be stored as a member in Class article.
No polymorphism is needed here.
The items can be of different types: books(TAX type 3), toys(TAX type
1)
Or you could store only the type (books, toys), and do a lookup in a table type | TAX-type, if the TAX types will always be the same for the full range of each type.
But if you really have or need a derived class for each type (for example to store different properties), you could call a virtual function in the derived classes CalcTax() for example.
An array with (baseclass*) pointers to the items could be created, and you can loop through that array, and call CalcTax() on each item, which will call the correct virtual function.
For example:
#include <iostream>
class Base
{
public:
virtual CalcTax() = 0;
};
class Type_1 : public Base
{
public:
virtual CalcTax() {std::cout << "Type_1\n";}
};
class Type_2
{
public:
virtual CalcTax() {std::cout << "Type_2\n";}
};
int main()
{
Base *arrItems[2]; // or better use std::vector<> etc.
Type_1 t1; // just a quick demo of polymorphism
Type_2 t2;
arrItems[0] = (Base*)&t1;
arrItems[1] = (Base*)&t2;
for (int i = 0; i < 2; ++i) {
arrItems[i]->CalcTax();
}
return 0;
}
I need some help on a strange mix between function pointers and templates...
My target :
You have a class : template<typename B> class A, and A instanciate a B member. Now I want to acces B getter/setter.
I tried this :
class B_example
{
public:
B_example(int v):m_var(v){}
int getVar() { return m_var; }
void setVar(int v) { m_var = v; }
private:
int m_var;
};
template<typename B> class A
{
public:
A():m_b(B(5))
{
get = &m_b.getVar;
set = &m_b.setVar;
}
int (B::*get)();
void (B::*set)(int);
private:
B m_b;
};
int main(int argc, char** argv)
{
A<B_example> A_instance;
B_example B_instance(5);
int a = (A_instance.get*)();
std::cout << a << std::endl;
}
Thank's for any help.
Alexandre
First, fix the syntax errors:
get = &B::getVar;
set = &B::setVar;
Then, the member-function pointer needs to be called on an object. Without knowing the purpose of these strange pointers, I can't guess what you want to do here. Maybe you want to call on B_instance:
int a = (B_instance.*A_instance.get)();
Or maybe you want to call it on the m_b object within A_instance; but you can't do that because it's private. If that's the case, you probably just want regular member functions, rather than weird function pointers
int get() {return m_b.getVar();}
void set(int v) {m_b.setVar(v);}
These:
get = &m_b.getVar;
set = &m_b.setVar;
Should be:
get = &B::getVar;
set = &B::setVar;
And (A_instance.get*)() should be (B_instance.*A_instance.get)().
I am making a toy programming language in c++, but i have run into a problem. I have noticed that in c++ a stack can only store one type of data. I was wondering if there was an easy way to fix this problem, such as by storing in the stack a byte array of each object. I was wondering if anyone knows how the jvm overcomes this issue. The types i would need to store on the stack would be char, short, int, float, double, strings, arrays, and references to objects. I understand that the jvm stack might be more of an abstraction, but if it is i would still like to know how they have accomplished it. If it makes any difference, i am only planning to target windows computers.
You know C++ has support for inheritance and polymorphism, right? A far easier way to do this is to derive all your tokens from a common base class, and make a stack of Base * objects, for instance:
#include <iostream>
#include <string>
#include <stack>
#include <memory>
class base {
public:
virtual void print_token() = 0;
virtual ~base() {}
};
class token_a : public base {
public:
token_a(int n) : n(n) {}
virtual void print_token() { std::cout << n << std::endl; }
private:
int n;
};
class token_b : public base {
public:
token_b(std::string s) : s(s) {}
virtual void print_token() { std::cout << s << std::endl; }
private:
std::string s;
};
int main(void) {
std::stack<std::shared_ptr<base> > my_stack;
my_stack.push(std::shared_ptr<base>(new token_a(5)));
my_stack.push(std::shared_ptr<base>(new token_b("a word")));
for ( int i = 0; i < 2; ++i ) {
std::shared_ptr<base> pb = my_stack.top();
pb->print_token();
my_stack.pop();
}
return 0;
}
outputs:
paul#local:~/src/cpp/scratch$ ./stack
a word
5
paul#local:~/src/cpp/scratch$
The way I have solved this problem (in C, for a lisp interpretr, about 25 years ago, but same idea applies today) is to have a struct with a type and a union inside it:
struct Data // or class
{
enum kind { floatkind, intkind, stringkind, refkind };
Kind kind;
union
{
double f;
int i;
std::string s;
Data* r; // reference, can't use Data &r without heavy trickery.
} u;
Data(double d) { kind = floatkind; u.f = d; }
Data(int i) { kind = intkind; u.i = i; }
...
}
std::stack<Data> st;
st.push(Data(42));
st.push(Data(3.14));
Just a guess, but the jvm probably treats everything as an object, so the stack is simply a collection of objects.
You can do the same, if you create a base data object class and derive all your supported data types from it.
First of all sorry if i've chosen wrong title, but wasn't sure how to name it.
Code structure first:
//== 1st file ==
class A {
private:
int x;
public:
int GetX() { return x; }
};
//== 2nd file ==
class B {
private:
A ob1;
public:
virtual A & GetARef() { return ob1; }
};
class C : public B {
private:
A ob2;
public:
A & GetARef() { return ob2; }
};
class D : public B {
public:
// something else w/e
};
//== 3rd file ==
class E {
private:
std::map <int,C> m;
public:
C* GetCPtr(int idx) { return &m[idx]; }
};
//== 4th file ==
void foo(E & E_Obj) {
std::vector <B*> v;
v.push_back(E_Obj.GetCPtr(0));
v.push_back(/*some pointer to D class*/);
Boo(v); // FORGOT TO ADD IT ! Sorry
};
//== 5th file ==
void Boo(std::vector <B*> & v) {
std::cout << v[0]->GetARef().GetX(); // returns B::ob1 's x instead of C::ob2 's x.
};
As wrote in comments, Boo gets wrong 'x'. I just wonder if it's because that pointers go 'out of scope' or I misdesigned something wrong. How to fix that, so I can get proper x (C::ob2 's one).
Sorry for kinda strange class names etc., but orginal code is much longer, so I tried to show the situation only.
#edit
Forgot to add that in Foo() it returns what i expect - C::ob2 's x.
This is the essence of what you are doing
#include <iostream>
using namespace std;
class Base{
const int b = 0;
public:
virtual const int& getInt(){
return b;
}
};
class LeafOverriding : public Base{
const int l = 1;
public:
virtual const int& getInt(){
return l;
}
};
class Leaf : public Base{
};
int main(){
cout << Leaf().getInt() << '\t' << LeafOverriding().getInt() << endl;
}
and it has no problems (i.e. it does indeed output 0 1). I would say that your snippet -- which does not compile, btw -- does not represent the real code.
I'm so lazy I forced you to compile it with C++11 support, because of const int b = 0 and const int l = 1 :)
Sorry for not leaving reply in comments, but I decided it's worth whole post. Also sorry for such late reply. I've spent whole day and night digging slowly through code, since you've proved that my coding was fine (except few typos in example code, sorry for that). Practically after rewriting code letter after letter I finally found the troublemaker somewhere I would normally never look for. My co-worker while sorting some things was switching not the pointers in related vector but their content.
Something like that
vector <E*> v;
// ...
*v[i] = ...
instead of
v[i] = ...
After fixing that, it indeed works as intented. Thanks for your help and clearing things out. Also sorry for wasting your time.