Some time ago, Borland have introduced in their BCB evironment an extension to C++ language. This extension is a __closure keyword. The question is, if it is possible to implement such functionality in plain C++ or C++11? If you are not familiar with __closure keyword, below code provides explanation in comments.
Thanks in advance!
Toreno
#include <stdio.h>
// __closure keyword is used here !
typedef void (__closure * MemberCallback)(int x, int y, int z);
class A
{
private:
MemberCallback callback;
public:
A() : callback(NULL)
{
}
void setCallback(MemberCallback newCallback)
{
callback = newCallback;
}
void call(int x, int y, int z)
{
if(callback)
callback(x, y, z);
else
printf("NOT SET(%i, %i, %i)\n", x, y, z);
}
};
class B
{
public:
void func1(int x, int y, int z)
{
printf("FUNC 1(%i, %i, %i)\n", x, y, z);
}
void func2(int x, int y, int z)
{
printf("FUNC 2(%i, %i, %i)\n", x, y, z);
}
};
int main()
{
// A and B classes do not know about each other. There is no possibility
// to for inheritance because B class can implement multiple instances
// of callback function
A a;
B b;
a.call(1, 2, 3); // Prints: NOT SET(1, 2, 3)
a.setCallback(b.func1);
a.call(4, 5, 6); // Prints: FUNC 1(4, 5, 6)
a.setCallback(b.func2);
a.call(7, 8, 9); // Prints: FUNC 2(7, 8, 9)
return 0;
}
std::function is exactly what you're looking for. If you want to learn how such mechanism is actually implemented in the library, here's a good series of blog posts on it. Combine that with lambda functions for capturing of local variables.
Re-hash of the previous answer with the full code, for others like me that want a quick reference to a common pattern:
#include <functional>
#include <stdio.h>
// __closure replacement
typedef std::function<void(int x, int y, int z)> MemberCallback;
class A
{
public:
void setCallback( MemberCallback newCallback ) {
callback_ = newCallback;
}
void call( int x, int y, int z ) {
if ( callback_ )
callback_( x, y, z );
else
printf( "NOT SET(%i, %i, %i)\n", x, y, z );
}
private:
MemberCallback callback_;
};
class B
{
public:
void func1( int x, int y, int z ) {
printf( "FUNC 1(%i, %i, %i)\n", x, y, z );
}
void func2( int x, int y, int z ) {
printf( "FUNC 2(%i, %i, %i)\n", x, y, z );
}
};
int main( )
{
// A and B classes do not know about each other. There is no possibility
// to for inheritance because B class can implement multiple instances
// of callback function
A a;
B b;
a.call( 1, 2, 3 ); // Prints: NOT SET(1, 2, 3)
a.setCallback( [&b](int x, int y, int z){ b.func1(x, y, z); } );
a.call( 4, 5, 6 ); // Prints: FUNC 1(4, 5, 6)
a.setCallback( [&b](int x, int y, int z){ b.func2(x, y, z); } );
a.call( 7, 8, 9 ); // Prints: FUNC 2(7, 8, 9)
return 0;
}
Output:
NOT SET(1, 2, 3)
FUNC 1(4, 5, 6)
FUNC 2(7, 8, 9)
Related
I'm following this tutorial on voxel terrain generation in Godot. However, I'm using C++ instead of GDScript. I got to about 7:08. The code is pretty much exactly translated and it compiles fine. However, when I try to open the project in Godot I get the Godot Engine has stopped working. A problem caused the program to stop working correctly... error. I don't know what's happening. When I delete the dll from the project it opens fine. Before, I got the official example to compile perfectly.
When I run the shell script Godot_v3.5.1-stable_win64_console.cmd instead of the executable the following error gets printed:
ERROR: Another resource is loaded from path 'res://Chunk.gdns' (possible cyclic resource inclusion).
at: (core/resource.cpp:79)
chunk.h:
#ifndef CHUNK_H
#define CHUNK_H
#include <vector>
#include <Godot.hpp>
#include <StaticBody.hpp>
#include <SurfaceTool.hpp>
#include <ArrayMesh.hpp>
#include <Mesh.hpp>
#include <MeshInstance.hpp>
namespace godot {
const Vector3 VERTICES[] = {
Vector3(0, 0, 0),
Vector3(1, 0, 0),
Vector3(0, 1, 0),
Vector3(1, 1, 0),
Vector3(0, 0, 1),
Vector3(1, 0, 1),
Vector3(0, 1, 1),
Vector3(1, 1, 1),
};
const Vector3 DIMENSION = Vector3(16, 64, 16);
const unsigned char TOP[] = {2, 3, 7, 6};
const unsigned char BOTTOM[] = {0, 4, 5, 1};
const unsigned char LEFT[] = {6, 4, 0, 2};
const unsigned char RIGHT[] = {3, 1, 5, 7};
const unsigned char FRONT[] = {7, 5, 4, 6};
const unsigned char BACK[] = {2, 0, 1, 3};
struct Block {};
class Chunk : public StaticBody {
GODOT_CLASS(Chunk, StaticBody)
private:
std::vector<Block> blocks;
SurfaceTool* st;
ArrayMesh* mesh;
MeshInstance* meshInstance;
public:
void Update();
void CreateBlock(const unsigned char x, const unsigned char y, const unsigned char z);
void CreateFace(const unsigned char* indices, const unsigned char x, const unsigned char y, const unsigned char z);
Chunk();
~Chunk();
static void _register_methods();
void _init();
void _process(float delta);
};
}
#endif
chunk.cpp:
#include "chunk.h"
using namespace godot;
void Chunk::_register_methods() {
register_method("_process", &Chunk::_process);
}
Chunk::Chunk() {}
Chunk::~Chunk() {
delete st;
delete mesh;
delete meshInstance;
}
void Chunk::_init() {
st = new SurfaceTool();
mesh = nullptr;
meshInstance = nullptr;
Update();
}
void Chunk::_process(float delta) {}
void Chunk::Update() {
// Unload chunk
if (meshInstance != nullptr) {
meshInstance->call_deferred("queue_free");
meshInstance = nullptr;
}
mesh = new ArrayMesh();
meshInstance = new MeshInstance();
st->begin(Mesh::PRIMITIVE_TRIANGLES);
for (unsigned char x = 0; x < DIMENSION.x; x++) {
for (unsigned char y = 0; y < DIMENSION.y; y++) {
for (unsigned char z = 0; z < DIMENSION.z; z++) {
CreateBlock(x, y, z);
}
}
}
st->generate_normals(false);
st->commit(mesh);
meshInstance->set_mesh(mesh);
add_child(meshInstance);
meshInstance->create_trimesh_collision();
}
void Chunk::CreateBlock(const unsigned char x, const unsigned char y, const unsigned char z) {
CreateFace(TOP, x, y, z);
CreateFace(BOTTOM, x, y, z);
CreateFace(LEFT, x, y, z);
CreateFace(RIGHT, x, y, z);
CreateFace(BACK, x, y, z);
CreateFace(FRONT, x, y, z);
}
void Chunk::CreateFace(const unsigned char* indices, const unsigned char x, const unsigned char y, const unsigned char z) {
auto offset = Vector3(x, y, z);
// Get corners
auto a = VERTICES[indices[0]] + offset;
auto b = VERTICES[indices[1]] + offset;
auto c = VERTICES[indices[2]] + offset;
auto d = VERTICES[indices[3]] + offset;
PoolVector3Array triangleOne;
triangleOne.push_back(a);
triangleOne.push_back(b);
triangleOne.push_back(c);
PoolVector3Array triangleTwo;
triangleTwo.push_back(a);
triangleTwo.push_back(c);
triangleTwo.push_back(d);
st->add_triangle_fan(triangleOne);
st->add_triangle_fan(triangleTwo);
}
When I create a function such as:
int addThree(int x=1, int y=1, int z=1)
I want to call the function such that it uses the default arguments for x and z, but not y.
Some attempts have been addThree(5,,5) and addThree(5,NULL,5), but neither work effectively.
The default arguments must be at the last of your list, so do as follows
int addThree(int y , int x = 1, int z = 1)
{
//some stuff
return someInt;
}
, hence you can call it as
int ans = addThree(4);
Default arguments in C++, need to be specified in immediate succession, and cannot be succeeded by a non-default parameter.
So, something like
int sum(int x = 0, int y, int z = 0) {
return (x + y + z);
}
is forbidden in C++
The function needs to be as follows:
#include <iostream>
int sum(int x, int y = 0, int z = 0) {
return (x + y + z);
}
int main() {
std::cout << sum(1) << "\n";//calls sum(1,0,0)
std::cout << sum(1,2) << "\n";//calls sum(1,2,0)
return 0;
}
However, while specifying default arguments, you always need to take care in function overloading. The overloaded functions cannot be called ambiguously..
So a code like:
#include <iostream>
int sum(int x, int y = 0, int z = 0) {
return (x + y + z);
}
float sum(int x, float y = 0.0, float z = 0.0) {
return (float(x) + y + z);
}
int main() {
std::cout << sum(1) << "\n";
return 0;
}
does not compile and righty produces ambiguity error, as the compiler does not understand
Whether it should call the first sum, or the second sum.
If you're consistently passing a value for one parameter and using the defaults for the others, you can rearrange the parameters to the one you need to pass is first, and the ones for which you use defaults come later. But that only works if it's essentially always the same ones for which you supply a value vs. use the defaults.
Otherwise, if you need something similar to the basic capability badly enough, you can pass an instance of a class, and have that class implement the named parameter idiom.
class triplet {
int x_ {1};
int y_ {1};
int z_ {1};
public:
triplet &x(int val) { x_ = val; return *this; }
triplet &y(int val) { y_ = val; return *this; }
triplet &z(int val) { z_ = val; return *this; }
int x() const { return x_; }
int y() const { return y_; }
int z() const { return z_; }
};
int addThree(triplet const &t) {
return oldAddThree(t.x(), t.y(), t.z());
}
int ans = addThree(triplet().x(4));
This lets you use the defaults for as many or few of the values you need as you want, and override only those that you actually want to. On the other hand, it does add a fair amount of syntactic overhead, so you have to want the capability pretty badly to bother.
I feel that its unlikelier than not, but I'd like to see if a function can deduce its parameters from a trivially wrapped struct. For example:
struct wrapped_float
{
float f;
wrapped_float(float f) : f(f) {}
};
float saxpy(float a, float x, float y)
{
return a * x + y;
}
int main()
{
wrapped_float a = 1.1, x = 2.2, y = 3.3;
auto result = saxpy(a, x, y); // ofc compile error
}
The motivation behind this is to make a lightweight wrapper around GDI calls with device context handles (HDC). There exists a lot of legacy code which uses HDCs and I'd like to refactor a lot of this code incrementally. My strategy is to make a lightweight wrapper around HDC like this:
#include <Windows.h>
struct graphics
{
HDC dc;
graphics(HDC dc) : dc(dc) {}
void rectangle(int x, int y, int w, int h)
{
Rectangle(dc, x, y, x + w, y + h);
}
};
void OnPaint(HDC dc)
{
Rectangle(dc, 1, 2, 3, 4);
}
int main()
{
HDC dc;
// setup dc here
graphics g = dc;
OnPaint(g);
}
So that if g can be implicitly transformed to HDC, then all legacy code will normally compile, but I can slowly refactor code to become like this:
void OnPaint(graphics g)
{
g.rectangle(1, 2, 3, 4);
}
Any recommendations are also welcome since this simply might not be possible in C++ (or any programming language).
From the comments, I was not aware that C++ had a casting operator. The simple solution is to add:
struct graphics
{
HDC dc;
graphics(HDC dc) : dc(dc) {}
void rectangle(int x, int y, int w, int h)
{
Rectangle(dc, x, y, x + w, y + h);
}
operator HDC()
{
return dc;
}
};
I have written cppUnit codes in testBMath.cc. I am able to write test cases for first three functions which are add,subtract and multiply. But I am not able to write test cases for Divide and Swap.I don't know how to handle divide by zero in test cases and how to check that numbers are swapped or not in cppUnit test cases.
testMath.h
#ifndef TEST_MATH_H__
#define TEST_MATH_H__
class testMath
{
public:
int Addition(int x, int y);
int Multiply(int x, int y);
int Subtraction(int x, int y);
int Division(int x, int y);
void swap(int &x, int &y);
};
#endif
testMath.cc
#include "testMath.h"
int testMath::Addition(int x, int y)
{
return (x + y);
}
int testMath::Multiply(int x, int y)
{
return (x * y);
}
int testMath::Subtraction(int x, int y)
{
return (x - y);
}
int testMath::Division(int x, int y)
{
if( b == 0 )
{
throw "Division by zero condition!";
}
return (a/b);
}
void swap(int &a, int &b)
{
int temp;
temp = b;
b = a;
a = temp;
}
testBMath.cc
#include <iostream>
#include <string>
#include <list>
#include "cppunit/TestCase.h"
#include "cppunit/TestFixture.h"
#include "cppunit/ui/text/TextTestRunner.h"
#include "cppunit/extensions/HelperMacros.h"
#include "cppunit/extensions/TestFactoryRegistry.h"
#include "cppunit/TestResult.h"
#include "cppunit/TestResultCollector.h"
#include "cppunit/TestRunner.h"
#include "cppunit/BriefTestProgressListener.h"
#include "cppunit/CompilerOutputter.h"
#include "netinet/in.h"
#include "testMath.h"
using namespace CppUnit;
using namespace std;
//-----------------------------------------------------------------------------
class testBMath : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE(testBMath);
CPPUNIT_TEST(testAddition);
CPPUNIT_TEST(testMultiply);
CPPUNIT_TEST(testSubtraction);
CPPUNIT_TEST(testDivision);
CPPUNIT_TEST(testSwap);
CPPUNIT_TEST_SUITE_END();
public:
void setUp(void);
void tearDown(void);
protected:
void testAddition(void);
void testMultiply(void);
void testSubtraction(void);
void testDivision(void);
void testSwap(void);
private:
testMath *mTestObj;
};
//-----------------------------------------------------------------------------
void testBMath::setUp(void)
{
mTestObj = new testMath();
}
void testBMath::testAddition(void)
{
CPPUNIT_ASSERT(5 == mTestObj->Addition(2,3));
}
void testBMath::testMultiply(void)
{
CPPUNIT_ASSERT(6 == mTestObj->Multiply(2,3));
}
void testBMath::testSubtraction(void)
{
CPPUNIT_ASSERT(2 == mTestObj->Subtraction(5,3));
}
void testBMath::testDivision(void)
{
CPPUNIT_ASSERT(6 == mTestObj->Division(12,2));
//But for divide by zero how should I write
}
void testBMath::testSwap(void)
{
//How should I check for swap
}
void testBMath::tearDown(void)
{
delete mTestObj;
}
//-----------------------------------------------------------------------------
CPPUNIT_TEST_SUITE_REGISTRATION( testBMath );
int main(int argc, char* argv[])
{
// informs test-listener about testresults
CPPUNIT_NS::TestResult testresult;
// register listener for collecting the test-results
CPPUNIT_NS::TestResultCollector collectedresults;
testresult.addListener (&collectedresults);
// register listener for per-test progress output
CPPUNIT_NS::BriefTestProgressListener progress;
testresult.addListener (&progress);
// insert test-suite at test-runner by registry
CPPUNIT_NS::TestRunner testrunner;
testrunner.addTest (CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest ());
testrunner.run(testresult);
// output results in compiler-format
CPPUNIT_NS::CompilerOutputter compileroutputter(&collectedresults, std::cerr);
compileroutputter.write ();
// return 0 if tests were successful
return collectedresults.wasSuccessful() ? 0 : 1;
}
My suggestions, change exception from const char* to something more meaningful, like std::runtime_error:
int testMath::Division(int x, int y)
{
if( b == 0 )
{
throw std::runtime_error("Division by zero condition!");
}
return (a/b);
}
Than the test's would look like:
void testBMath::testDivision(void)
{
CPPUNIT_ASSERT(6 == mTestObj->Division(12,2));
CPPUNIT_ASSERT_THROW(mTestObj->Division(12,0), std::runtime_error);
}
void testBMath::testSwap(void)
{
int x = 2;
int y = 3;
mTestObj->swap(x, y);
CPPUNIT_ASSERT(x == 3 && y == 2);
}
For example, we have this class:
class Coord
{
double x;
double y;
double z;
public:
Coord() { x = y = z = 0; }
void set(double xx, double yy, double zz)
{
x = xx;
y = yy;
z = zz;
}
void set_x(double xx) { x = xx; }
void set_y(double yy) { y = yy; }
void set_z(double zz) { z = zz; }
double get_x() { return x; }
double get_y() { return y; }
double get_z() { return z; }
};
On these 7 methods we can set and get x,y and z of a coordinate. I am interested in create less methods set() and get() where I can call something like that:
int main()
{
Coord c;
c.set_x(5); /* only set x */
c.set_y(6); /* or y */
c.set_z(7); /* or z */
c.set(1,2,5); /* or setting x, y and z */
c.get_x(); /* only get x */
c.get_y(); /* or y */
c.get_z(); /* or z */
}
If the Coord class is that simple, it could also be a struct.
Anyway you can write something like:
class Coord
{
public:
enum xyz {x = 0, y, z};
Coord() : vec{x, y, z} {}
template<xyz C> void set(double v) { vec[C] = v; }
template<xyz C> double get() const { return vec[C]; }
void set(double xx, double yy, double zz)
{
set<Coord::x>(xx);
set<Coord::y>(yy);
set<Coord::z>(zz);
}
private:
double vec[z + 1];
};
and use the class this way:
Coord c;
c.set<Coord::x>(5); /* only set x */
c.set<Coord::y>(6); /* or y */
c.set<Coord::z>(7); /* or z */
c.set(1,2,5); /* or setting x, y and z */
c.get<Coord::x>(); /* only get x */
c.get<Coord::y>(); /* or y */
c.get<Coord::z>(); /* or z */
getters and setters are meant to protect your data and provide encapsulation.
For example they allow you to add side effects to getting and setting operations (such as writing to a log), or allow you to catch invalid values early before they cause horrible problems later (For example preventing values greater than n being set).
Here's a brief and contrived setter example:
void set_x(int x)
{
// prevent an invalid value for x
if( x > 11 ) x = 11;
// set x
this.x = x;
// log the operation
log("user set x to {0}", x);
}
Assuming your c.set.x(5) example is not using some whacky preprocessor macros, it would require that the Coord class have a member variable called set with methods
x()
y()
z()
This would require just as much code as writing a set_x(), set_y() and set_z() method in your Coord class, but the methods would not belong to the class Coord, instead belonging to another class that is itself used as a member variable of Coord. Doing so would not really make any logical sense... the x, y, and z values belong to Coord and operations on them are operations on the Coord.
Furthermore the methods x() y() and z() would no longer obey the general principle of making methods verbs. Anyone reading the class with those methods would have no idea what function z() is supposed to do!
It would also create a refactoring nightmare: If for example in the future a business requirement appeared that meant no Coords could ever have values of x greater than 21 somone maintaining your code would have to change a class that is a member of Coord rather than the Coord class itself.
Encapsulation with getter and setter methods is often a really good idea and in C++ with the benefit of inlining it can even add no runtime overhead. But keep to the principle "Make everything as simple as possible, but not simpler." In other words get_x() and set_x() are widely understood, useful, easily refactored, convenient, self-documenting and performant... other approaches are likely to be less so.
First: Your usage of c.set.x would not work because you would call a public element set on your object c and where set has a public element x.
I find both classes lack standards of clean code and usual style of getter and setter - even without specifying any language.
A usual way would be to create the following:
class Coord
{
double x;
double y;
double z;
public:
Coord() {
x = 0;
y = 0;
z = 0;
}
Coord(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
void setX(double x) { this.x = x; }
void setY(double y) { this.y = y; }
void setZ(double z) { this.z = z; }
double getX() { return x; }
double getY() { return y; }
double getZ() { return z; }
};
Though some prefer to use m_x as setter variable parameter or any other convention.
Anyhow everyone would directly understand your code. Is able to set and get coordinate values for x, y, z and it would look pretty standard-default-behaviour if someone does following:
Coord P(10, 15, 20);
std::cout << P.getX() << " " << P.getY() << std::endl;
P.setX(-10);
P.setZ(40);
You've already gotten some good answers, but you could also use an enum if you really want a syntax with fewer setters and getters. The client syntax can get a little clunky and awkward, but it of course depends on what you're looking for!
#include <iostream>
class Coord {
public:
enum Axis {
X = 0,
Y,
Z,
NUM_AXES
};
// Using extended initializer lists (C++11)
Coord() : axes_{0, 0, 0} {}
Coord(double x, double y, double z) : axes_{x, y, z} {}
void set(Axis a, double d) {
axes_[a] = d;
}
double get(Axis a) const {
return axes_[a];
}
private:
double axes_[NUM_AXES];
// Copy constructor and assgn. operator included for good measure
Coord(const Coord &);
void operator=(const Coord &);
};
int main()
{
Coord c(1, 2, 3);
std::cout << "X: " << c.get(Coord::X) << std::endl;
std::cout << "Y: " << c.get(Coord::Y) << std::endl;
std::cout << "Z: " << c.get(Coord::Z) << std::endl;
c.set(Coord::Y, 4);
std::cout << "Y: " << c.get(Coord::Y) << std::endl;
return 0;
}
This strange code does exactly what you ask - just C++ fun. Don't do this!
#include <iostream>
using namespace std;
class Coord {
double x;
double y;
double z;
public:
class Setter {
public:
Setter(Coord& coord) : c(coord) {}
void x(double value) { c.x = value; }
void y(double value) { c.y = value; }
void z(double value) { c.z = value; }
void operator()(double x, double y, double z) { c.x = x; c.y = y; c.z = z; }
private:
Coord& c;
};
class Getter {
public:
Getter(Coord& coord) : c(coord) {}
double x() { return c.x; }
double y() { return c.y; }
double z() { return c.z; }
private:
Coord& c;
};
Setter set;
Getter get;
Coord() : set(*this), get(*this) { x = y = z = 0; }
friend class Setter;
};
int main()
{
Coord c;
cout << c.get.x() << " " << c.get.y() << " " << c.get.z() << endl;
c.set.x(1);
c.set.y(2);
c.set.z(3);
cout << c.get.x() << " " << c.get.y() << " " << c.get.z() << endl;
c.set(5, 6, 7);
cout << c.get.x() << " " << c.get.y() << " " << c.get.z() << endl;
return 0;
}
Output:
0 0 0
1 2 3
5 6 7
The more or less standard way to expose this, if validation is not a concern, is to return mutable references from the non-const accessor, and values from the const one. This allows you to separate the interface from storage, while not making the syntax too heavy.
private:
double m_x, m_y, m_z;
public:
double & x() { return m_x; }
double & y() { return m_y; }
double & z() { return m_z; }
double x() const { return m_x; }
double y() const { return m_y; }
double z() const { return m_z; }
This will allow c.x() to obtain the value of the x coordinate whether the Coord object is const or not, and allows setting the value using the syntax c.x() = value.
In the interest of completeness, you can get exactly the syntax you want using the following code, but I would strongly recommend against it. It is a lot of extra code, provides no real benefit, and creates a syntax that is uncommon and most programmers will not find it intuitive.
The technique creates two nested classes getters and setters and exposes instances of them as public members of Coord.
This is provided as an example of how to achieve the result you asked for, but I do not recommend this approach.
class Coord
{
private:
double x, y, z;
public:
Coord();
Coord(double, double, double);
class setters {
friend class Coord;
private:
explicit setters(Coord &);
public:
setters(setters const &) = delete;
setters & operator=(setters const &) = delete;
void x(double) const;
void y(double) const;
void z(double) const;
private:
Coord & coord;
};
friend class setters;
class getters {
friend class Coord;
private:
explicit getters(Coord const &);
public:
getters(getters const &) = delete;
getters & operator=(getters const &) = delete;
double x() const;
double y() const;
double z() const;
private:
Coord const & coord;
};
friend class getters;
setters const set;
getters const get;
};
Coord::Coord() : x(0), y(0), z(0), set(*this), get(*this) { }
Coord::Coord(double px, double py, double pz) : x(px), y(py), z(pz), set(*this), get(*this) { }
Coord::setters::setters(Coord & c) : coord(c) { }
void Coord::setters::x(double px) const {
coord.x = px;
}
void Coord::setters::y(double py) const {
coord.y = py;
}
void Coord::setters::z(double pz) const {
coord.z = pz;
}
Coord::getters::getters(Coord const & c) : coord(c) { }
double Coord::getters::x() const {
return coord.x;
}
double Coord::getters::y() const {
return coord.y;
}
double Coord::getters::z() const {
return coord.z;
}
(Demo)
Actually the function can be reduce based on your requirement as follows,
class Coord
{
double x;
double y;
double z;
public:
Coord() {
x = 0;
y = 0;
z = 0;
}
void GetValues(double* x=NULL, double* y=NULL, double* z=NULL);
void SetValues(double x=0, double y=0, double z=0)
/* You can use constructors like below to set value at the creation of object*/
Coord(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
/*You can set the values of x, y & z in a single function as follows. It can be used at any time without restriction */
void SetValues(double x, double y, double z)
{
if(x > 0) //It is optional to use condition so that you can update any one variable aloen by sending other two as ZERO
{
this.x = x;
}
if(y > 0)
{
this.y = y;
}
if(z > 0)
{
this.z = z;
}
}
/*You can Get the values of x, y & z in a single function as follows. Pass By Reference id the concept you need */
void GetValues(double* x, double* y, double* z)
{
if(x != NULL) //It x is not null.
{
x = this.x;
}
if(y != NULL)
{
y = this.y;
}
if(z != NULL)
{
z= this.z;
}
}
};
while calling you can call like the following,
SetValues(10, 20, 0); //To set x and y values alone.
double x1 = 0;double y1 = 0;double z1 = 0;
GetValues(&x1, &y1, &z1)//It will return the values x1 y1 and z1 as 10, 20 & 0
You cannot do exactly what you want.
In
c.set.x(5); /* only set x */
the c.set subexpression is retrieving a field set from c (unless set is a #define-d macro, but that would be silly).