Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Given a header file that has different functions (function1 and function2): what is the best practice of sharing the same default arguments?
class MyClass {
public:
virtual ... function1(..., int param1 = 48, int param2 = getStuff(99)) = 0;
virtual ... function2(..., int param1 = 48, int param2 = getStuff(99)) = 0;
}
Using something like
#define PARAM1 = 48
#define PARAM2 = getStuff(99)
seems rather inconvenient. I am fairly new to C++ so I don't know whats the best practice in this case. Should I instead create some private constant inside of MyClass?
You may do:
class MyClass {
public:
void function1(int param1 = default_param1, int param2 = default_param2());
void function2(int param1 = default_param1, int param2 = default_param2());
private:
static const int default_param1 = 48;
static int default_param2() { return getStuff(99); } // assuming it might change
};
I see your functions are virtual - be aware that the default parameters are not inherited!
int getStuff(int n)
{
return n;
}
class MyClass
{
public:
static constexpr int DefaultParam1 = 48;
static constexpr int DefaultParam2 = 99;
virtual ~MyClass() = default;
virtual void function1(int param1 = DefaultParam1, int param2 = DefaultParam2) = 0;
inline void function2()
{
function1(getStuff(DefaultParam1), getStuff(DefaultParam2));
}
inline void function2(int param1)
{
function1(param1, getStuff(DefaultParam2));
}
virtual void function2(int param1, int param2) = 0;
};
Have a look at function2 in my example, it is overloaded with inline functions. Advantage:
class MC : public MyClass
{
public:
virtual void function1(int param1, int param2)
{
}
using MyClass::function2;
virtual void function2(int param1, int param2)
{
}
};
int main()
{
MC mc;
((MyClass&)mc).function1();
mc.function2();
return 0;
}
function1 requires a cast to be used with default parameters (without repeating them in the inheriting class), function2 does not (unfortunately, you need the using clause to make the overloads visible in the inheriting class, though).
Side note: I'm not telling the first approach is wrong or bad, I'm just showing an alternative...
Related
Hiho,
im working on some stuff with instances and wondering, is it possible to create a generic instance creation function for a class/struct and its following derivates.
I have 2 Problems and a question for possibility:
to make it work, that the generic function can at least deliever an instance of the class/struct itself, the funtion is living/existing in. --> got undefined reference error
to make it work , that the generic function can deliever several types of instances --> got undefined reference type error
is it possible to make it work, that the generic function deliever types of future derivate types, by impplementing further template declarations in these derivates. So the base class with the generic function dont need to know about them( and by my understanding of the situation, never can , because how knows what future children/derivates will follow )
I prepared a example for better understanding:
//base.hpp
struct base {
base(int param1, int param2) : a(param1), b(param2)
{}
private:
int a,b;
public:
template <typename T> static T createInstanceGeneric(int param1, int param2){
return T(param1, param2);
}
//Thats of course working//
static base createInstance(int param1, int param2) {
return base(param1, param2);
}
void update(int param2){
_update(0, param2);
}
void process() { int tmp = a; a = b; b = tmp }
protected:
void _update(int param1, int param2){
a = param1;
b = param2;
}
}
//END base.hpp
//childOne.hpp
#include "base.hpp"
struct childOne : public base {
childOne(int param1, int param2) : base(param1, param2 ){}
//Thats of course working//
static base createInstanceOfBase(int param1, int param2) {
return base::createInstance(param1, param2);
}
static childOne createInstanceOfSelfViaGeneric(int param1, int param2) {
return base::createInstanceGeneric<childOne>(param1, param2);
}
static base createInstanceOfBaseViaGeneric(int param1, int param2) {
return base::createInstanceGeneric<base>(param1, param2);
}
void update(int param1){
base::_update(param1, 0);
}
}
//END childOne.hpp
//app.cpp
#include "childOne.hpp"
void calledLaterForSomeStuff( const base& data ){
data.process();
}
void main()
{
base test1 = base::createInstance(0,1); //Working
test1.update(2);
calledLaterForSomeStuff(test1);
base test2 = childOne::createInstanceOfBase(0,1); //Working
test2.update(2);
calledLaterForSomeStuff(test2);
//undefined reference to `base base::createInstanceGeneric<base>(int param1, int param2)'//
//undefined reference to `base base::createInstanceGeneric(int param1, int param2)'//
base test3 = childOne::createInstanceOfBaseViaGeneric(0,1); //Question 1 and 2
test3.update(2);
calledLaterForSomeStuff(test3);
//undefined reference to `childOne base::createInstanceGeneric<childOne>(int param1, int param2)'
//undefined reference to `childOne base::createInstanceGeneric(int param1, int param2)'
childOne test4 = childOne::createInstanceOfSelfViaGeneric(0,1); //Question 3
test4.update(3);
calledLaterForSomeStuff(test4);
}
//END app.cpp
Ok, it works all out of the box.
I had the implemententation of the template inside the cpp file. But its only allowed in the hpp.
Now its works.
Case CLOSED
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.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
How would one go about calling a function by pointer without using the ampersand in the function call where I pass in a struct. I can only edit the function definition, not the way the function is being called. Call by reference can be used, but I would like to call by pointer, is there any way of doing this?
void Some_Func(struct TheStruct &My_struct){
My_struct->member = 4; // Would like to do this!
}
int main(){
Some_Func(My_Struct);
}
To be honest, I think this question was triggered by some misunderstanding....Lets assume you have this (working) code:
struct TheStruct { int member;};
void Some_Func(struct TheStruct &My_struct){
// some implementation
}
int main(){
TheStruct x;
Some_Func(x);
}
You say
I can only edit the function definition, not the way the function is being called.
...thus there is no way to make the function take a pointer as parameter. If there is a instance (not a pointer) passed as parameter in main and you are not allowed to change main, then you cannot magically make the parameter a pointer.
The only way to use -> inside the function is
void Some_Func(struct TheStruct &My_struct){
TheStruct* x = &MyStruct;
x->member = 4;
}
However, there is not a single reason to do so (unless the . on your keyboard is broken) and it makes the code confusing to read.
I am 90% sure this is not the answer you are looking for, but I'll post it for the remaining 10% of doubt anyway:
Have a look at std::addressof(T&). It gives you the pointer without using an ampersand.
When accessing an object by reference, you have to use the . operator to reach its members:
void Some_Func(TheStruct &My_struct) {
My_struct.member = 4;
}
int main() {
TheStruct My_struct;
Some_Func(My_Struct);
// or:
// TheStruct *My_struct = new My_struct;
// Some_Func(*My_Struct);
// delete My_struct;
}
When accessing an object by pointer, you have to use the -> or *. operator to reach its members:
void Some_Func(TheStruct *My_struct) {
My_struct->member = 4;
// or (*My_struct).member = 4;
}
int main() {
TheStruct My_struct;
Some_Func(&My_Struct);
// or:
// TheStruct *My_struct = new TheStruct;
// Some_Func(My_Struct);
// delete My_struct;
}
If you don't want to use the & operator to get the address of an object variable (maybe because it overrides operator&, for instance), you can use std::addressof() in C++11 and later:
int main() {
TheStruct My_struct;
Some_Func(std::addressof(My_Struct));
}
Or use boost::addressof:
#include <boost/utility.hpp>
int main() {
TheStruct My_struct;
Some_Func(boost::addressof(My_Struct));
}
Or implement addressof() manually:
template<class T>
T* my_addressof(T& arg)
{
return reinterpret_cast<T*>(
&const_cast<char&>(
reinterpret_cast<const volatile char&>(arg)
)
);
}
int main() {
TheStruct My_struct;
Some_Func(my_addressof(My_Struct));
}
This will work.
struct TheStruct {
int member;
};
void Some_Func(TheStruct &My_struct){
My_struct.member = 4;
}
int main(){
TheStruct My_Struct;
My_Struct.member = 5;
std::cout << My_Struct.member << std::endl;
Some_Func(My_Struct);
std::cout << My_Struct.member << std::endl;
return 0;
}
Output:
5
4
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I'm building an engine. I need to create a Timer class which will call a function by a pointer from a separate class. For example:
class MyTimer {
public:
void setTimeoutFunction( _pointer_, unsigned short timeoutMs ) {
// here we need to have a opportunity to store a _pointer_ to a function
}
void tickTimer() {
...
// here I need to call a function by a pointer
...
}
};
// Main class:
class MyAnyClass {
public:
void start() {
MyTimer myTimer;
myTimer.setTimeoutFunction( startThisFunc, 1500 ); // 1500ms = 1.5s
while ( true ) {
myTimer.tickTimer();
}
}
void startThisFunc() { ... }
}
In summation, how do you store a pointer to a function which belongs to some class and call that function by a pointer?
For your requirements, I might recommend making the timer a class template:
template <typename T>
struct MyTimer
{
using FuncPtr = void (T::*)();
MyTimer(FuncPtr ptr, T * obj, unsigned int timeout_ms)
: ptr_(ptr), obj_(obj), timeout_ms_(timeout_ms) {}
void tickTimer()
{
(obj_->*ptr_)();
}
FuncPtr ptr_;
T * obj_;
unsigned int timeout_ms_;
};
Usage:
struct MyAnyClass
{
void start()
{
MyTimer<MyAnyClass> myTimer(&MyAnyClass::startThisFunc, this, 1500);
while (true) { myTimer.tickTimer(); }
}
void startThisFunc() { /* ... */ }
};
In C++11 you can use std::function. A good guide on using it is here: http://en.cppreference.com/w/cpp/utility/functional/function
I created a new code snippet only containing the case you want.
#include <stdio.h>
#include <functional>
#include <iostream>
struct Foo {
Foo(int num) : num_(num) {}
void print_add(int i) const { std::cout << num_+i << '\n'; }
int num_;
};
int main()
{
// store a call to a member function
std::function<void(const Foo&, int)> f_add_display = &Foo::print_add;
const Foo foo(314159);
f_add_display(foo, 1);
return 0;
}
Consider the following code:
struct data
{
int foo;
int bar;
};
data a;
a.foo = 200;
a.bar = 300;
static void update(data* a, int rspec)
{
if (!rspec) //my data management
{
3rdPartyApi->CreateStream();
3rdPartyApi->PushData(a->foo);
3rdPartyApi->PushData(a->bar);
3rdPartyApi->CloseStream();
}
else // internal data management
{
3rdPartyApi->CreateStream();
3rdPartyApi->PushData(3rdPartyApi->BufferQueue);
3rdPartyApi->CloseStream();
}
3rdPartyApi->PushStream(3rdPartyApi->GetLastStreamBuffer().POD());
}
Lets say I change the value of a.foo or a.bar, and it requires me to call Update there-after the assignment. Can this be done, without actually calling Update() on each change manually?
[EDIT]
Note that the update function created is also assigned to a function pointer for
the third party API, so it can do it's own internal updating. So making the update function non-global is impossible, and thus is why the current update function is global.
[EDIT]
I also rewrote my example to be more understanding and correct to the actual API I'm using
e.g
3rdPartyApi->StreamUpdate((void (*)(void*, int))update);
Yes, you can. Use class methods for this. Pass a static method from your class to the 3rd party API as an update function.
class data
{
public:
void set_foo(int new_foo);
void set_bar(int new_bar);
int get_foo() const;
int get_bar() const;
// This is the update signature which the 3rd party API can accept.
static void update(void* ptr, int rspec);
private:
// These are private so we can control their access.
int foo;
int bar;
};
void data::set_foo(int new_foo)
{
foo = new_foo;
// 'this' is a special pointer for current data object.
update(this);
}
void data::set_bar(int new_bar)
{
bar = new_bar;
update(this);
}
int data::get_foo() const
{
return foo;
}
int data::get_bar() const
{
return bar;
}
// This is needed if the 3rd party API can only call C bindings.
// If it's a C++ API this is not needed.
extern "C" {
void data::update(void* ptr, int rspec)
{
if (!rspec) //my data management
{
// You have to cast to data* from void*.
data* data_ptr = reinterpret_cast<data*>(ptr);
3rdPartyApi->CreateStream();
3rdPartyApi->PushData(data_ptr->foo);
3rdPartyApi->PushData(data_ptr->bar);
3rdPartyApi->CloseStream();
}
else // internal data management
{
3rdPartyApi->CreateStream();
3rdPartyApi->PushData(3rdPartyApi->BufferQueue);
3rdPartyApi->CloseStream();
}
3rdPartyApi->PushStream(3rdPartyApi->GetLastStreamBuffer().POD());
}
} /* extern "C" */
Then:
3rdPartyApi->StreamUpdate(&data::update);
data a;
a.set_foo(200);
a.set_bar(300);
Note that use of a struct instead of a class is equally fine here. But the convention is to use classes in C++. There is only a minor difference which you can learn later.
It is hard to write code for foo, bar, and data, so let's make it more concrete:
class point
{
public:
int x_coord() const;
int y_coord() const;
void move_to(int new_x, int new_y);
private:
void update_3rd_party();
int x;
int y;
};
void point::move_to(int new_x, int new_y)
{
x = new_x;
y = new_y;
// whatever else needs to be done
update_3rd_party();
}
You need to make use of Observer design pattern or a slight variant of it.
See this example here.
The usual way would be to turn foo and bar into some type that overloads the assignment operator:
class updated_int {
int value;
public:
updated_int(int init = 0) : value(init) {}
updated_int &operator=(int new_val) {
value = new_val;
update();
return *this;
}
// You might want to declare this private and not implement it.
updated_int &operator=(updated_int const &r) {
value = r.value;
update();
return *this;
}
operator int() { return value; }
};
struct data {
updated_int foo;
updated_int bar;
}
data a;
a.foo = 1; // operator= will call update() automatically.