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
Ok Guys My Question here is simple.. I want to construct a getter and setter for diffrent value type.. Basically function overloading but with getters and setters.. i tried it like this
#include <iostream>;
class Vectors {
public:
Vectors() {};
Vectors(int a, int b) {
x = a, y = b;
}
int getX() {
return x;
}
int getY() {
return y;
}
float getX() {
return (float)x;
}
float getY() {
return (float) y;
}
friend Vectors operator+(const Vectors& v1, const Vectors& v2);
friend Vectors operator/(const Vectors& v1, const Vectors& v2);
protected:
int x, y;
private:
};
Vectors operator+(const Vectors& v1, const Vectors& v2) {
Vectors brandNew;
brandNew.x = v1.x + v2.x;
brandNew.y = v1.y + v2.y;
return (brandNew);
};
Vectors operator/(const Vectors& v1, const Vectors& v2) {
Vectors brandNew(v1.x / v2.x, v1.y/v2.y);
return brandNew;
}
int main() {
Vectors v1(2, 3);
Vectors v2(4, 5);
Vectors v3;
v3 = v1 + v2;
Vectors v4 = v1 / v2;
std::cout << "VECTOR 4 X : " << v4.getX() << std::endl;
std::cout << "VECTOR 4 Y : " << v4.getY() << std::endl;
std::cout << "Vector V3 X : " << v3.getX() << std::endl;
std::cout << "VECTOR V3 Y : " << v3.getX() << std::endl;
}
But Obviously it said cant do function overloading and the only type diffrent is return type..
Of course you're not using enough templates. Templates solve problems in C++. Use them. Love templates.
struct YeeTemplates {
float F;
template <typename T>
T getF() { return F; }
} y;
float f = y.getF<float>();
int i = y.getF<int>();
There's no way to overload a function without changing the arguments that I'm aware of. You need to either change the function name (call it getXFloat() or something) or just to the cast after calling the function like:
float the_x_value = static_cast<float>(vec.getX());
I would go for the second option.
You can't overload methods based on return type.
You can overload functions on it's input paramaters.
For example:
void fun1(int a,char b);
void fun1(float a,char b);
void fun1(float a,int a,char b);
http://www.tutorialspoint.com/cplusplus/cpp_overloading.htm
Another option you have is to not return the result as the return value. Instead:
...
void getX( float& result) const {
result = static_cast<float>(x);
}
void getX( int& result) const {
result = x;
}
...
Just adding to the list of options, not saying this is the best solution.
Related
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 10 months ago.
Improve this question
Problem Description
We have a vector<A> v containing for 4 objects. Each object has the following members x, y, z and w. Two objects are considered equal if the have the same x and y. In that case we merge the objects: we merge the vector w and we change the value of z if and only if the value of object that we want to check if it exists is different from zero. Else, we consider that it's a new object.
In the following source code, I was able to implement the algorithm, but the main issue that it is O(n²) (because I am looping over each object of the vector then using find_if to check if we have a similar object or not in the merged vector).
Question
Is it possible to make it simpler (that is, less time complexity)? I can't find a way.
Source Code
#include <iostream>
#include <vector>
#include <algorithm>
class A{
public:
int x, y, z;
std::vector<int> w;
};
int main() {
A a1, a2, a3, a4;
a1.x = 1; a1.y =2; a1.z = 3; a1.w = {1,2,3,4,5};
a2.x = 4; a2.y =5; a2.z = 6; a2.w = {6,7,8,9};
a3.x = 13;a3.y =14; a3.z = 14; a3.w = {10,11,12};
a4.x = 1; a4.y =2; a4.z = 0;a4.w = {44,45,46,47,48};
std::vector<A> v = {a1, a2, a3, a4};
std::vector<A> merged;
/* If 2 objects have the same x and y then merge objects */
for(const A&a:v){
auto it = std::find_if(merged.begin(),merged.end(),[&](const A&ma){
/*2 objects are the same if they have the same x and y*/
return a.x == ma.x and a.y == ma.y;
});
/* if 2 objects have the same x and y then merge*/
if(it != merged.end()){
/* Replace z in the merged vector only if a.z is different from 0*/
if(a.z != 0){
it->z = a.z;
}
/* Merge vectors*/
std::vector<int> mergedws;
std::set_union(a.w.begin(),a.w.end(),it->w.begin(),it->w.end(), std::back_inserter(mergedws));
it->w = mergedws;
} else {
/*We consider that a is a new object, since we couldn't find a similar object in the merged vector*/
merged.push_back(a);
}
}
/* merged vector should have 3 objects because a1 and a4 the same*/
std::cout <<"Number of Objects is: "<< merged.size() << std::endl;
for(const auto&m:merged){
std::cout <<"Element "<< m.x <<", "<< m.y <<","<<m.z << std::endl;
}
return 0;
}
You can do it in O(NlogN * MlogM) if you sort the input, and then do a linear pass to merge.
N is the length of v, and M is the length of the A::ws.
bool compare(const A & lhs, const A & rhs) {
return std::tie(lhs.x, lhs.y) < std::tie(rhs.x, rhs.y);
}
std::sort(v.begin(), v.end(), compare);
for (auto first = v.begin(), last = {}; it != v.end(); it = last) {
A result = *first;
last = std::upper_bound(first++, v.end(), result, compare);
for (; first != last; ++first) {
if (first->z) {
result.z = first->z;
}
// this is an in-place set_union
std::merge(result.w.begin(), result.w.end(), first->w.begin(), first->w.end());
auto unique_end = std::unique(result.w.begin(), result.w.end());
result.w.erase(unique_end, result.w.end());
}
merged.push_back(result);
}
The best way is to use std::unordered_map this will allow to find matching item in constant time, so final time complexity will be O(n):
class A {
public:
int x, y, z;
std::vector<int> w;
};
struct Point2d {
int x, y;
Point2d(int x, int y)
: x { x }
, y { y }
{
}
Point2d(const A& a)
: x { a.x }
, y { a.y }
{
}
};
bool operator==(const Point2d& l, const Point2d& r)
{
return l.x == r.x && l.y == r.y;
}
template <>
struct std::hash<Point2d> {
size_t operator()(const Point2d& p) const
{
std::hash<int> sub_hash {};
return (sub_hash(p.x) * 16777619) ^ sub_hash(p.y);
}
};
template <typename T, typename F>
std::unordered_map<Point2d, A> merge_collection(const T& collection, F f)
{
std::unordered_map<Point2d, A> r;
for (const auto& item : collection) {
f(r[item], item);
}
return r;
}
void merge_a(A& dest, const A& toMerge)
{
std::vector<int> w;
w.reserve(dest.w.size() + toMerge.w.size());
std::merge(dest.w.begin(), dest.w.end(), toMerge.w.begin(), toMerge.w.end(), std::back_inserter(w));
dest = {dest.x, dest.y, dest.z, std::move(w)};
}
template <typename T>
std::unordered_map<Point2d, A> merge_collection(const T& collection)
{
return merge_collection(collection, merge_a);
}
https://godbolt.org/z/Wz8vbz4h1
Suppose I want to write a class that represents an immutable normalized (norm == 1) vector in two dimensions along with a mutable int:
#include <cmath>
#include <iostream>
double norm2d(double x, double y)
{
return sqrt(x*x + y*y);
}
class NormalizedVector {
public:
NormalizedVector(double x, double y, int some_int)
: m_x(x / norm2d(x, y)), m_y(y / norm2d(x, y)), m_some_int(some_int){};
void set_some(int i) { m_some_int = i; }
private:
const double m_x;
const double m_y;
int m_some_int;
friend std::ostream& operator<< (std::ostream& os, const NormalizedVector& v) {
return os << "(" << v.m_x << "," << v.m_y << ")" << " : " << v.m_some_int;
}
};
int
main() {
NormalizedVector v { 1, 1 , 42};
std::cout << v << std::endl;
v.set_some(23);
std::cout << v << std::endl;
return 0;
}
Is it in this situation possible to avoid calling norm2d(x, y) twice in the ctor while still using initialization lists? Note that default-constructing members and assigning them in the ctor's body is not possible because the vector components are const.
I am well aware that this MWE is not very realistic but in the past I have for several times stumbled upon a situation where one function (or "some code") was required to compute values for multiple members in the initialization list and where in-body-assigning them was not an option because the corresponding members where either const or not zero-cost-default-constructable.
Yes, you can have a private constructor that takes an additional parameter, and delegate to that.
class NormalizedVector {
public:
NormalizedVector(double x, double y, int some_int)
: NormalizedVector(x, y, some_int, norm2d(x, y)) {};
void set_some(int i) { m_some_int = i; }
private:
NormalizedVector(double x, double y, int some_int, double norm)
: m_x(x / norm), m_y(y / norm), m_some_int(some_int){};
const double m_x;
const double m_y;
int m_some_int;
friend std::ostream& operator<< (std::ostream& os, const NormalizedVector& v) {
return os << "(" << v.m_x << "," << v.m_y << ")" << " : " << v.m_some_int;
}
};
I need implement the class Option_Pricer that encapsulates all the functions relevant to price both call and put options. The teacher is giving me a code listing (.cpp file) that I have to turn into a class. All the functions that I used in my class are therefore coming from the teacher. I simply have to implement them as a class.
Here is what I have done so far: I have split the code into two different files. One is called option_pricer.hpp and is used as an header for the main file option_pricer.cpp.
//option_pricer.hpp
#define _USE_MATH_DEFINES
#include <iostream>
#include <cmath>
class Option_Pricer {
private:
void init();
public:
double S;
double K;
double r;
double v;
double T;
double x;
double j;
public:
//Constructors
call_price();
put_price();
norm_pdf();
norm_cdf();
d_j() const;
// Assignment operator
call_price& operator = (const call_price& call);
put_price& operator = (const put_price& put);
};
Here is the main file:
//option_pricer.cpp
#define _USE_MATH_DEFINES
#include <iostream>
#include <cmath>
#include "option_pricer.hpp"
double Option_Pricer::norm_pdf(const double& x) const {
return (1.0/(pow(2*M_PI,0.5)))*exp(-0.5*x*x);
}
double Option_Pricer::norm_cdf(const double& x) const {
double k = 1.0/(1.0 + 0.2316419*x);
double k_sum = k*(0.319381530 + k*(-0.356563782 + k*(1.781477937 + k*(-1.821255978 + 1.330274429*k))));
if (x >= 0.0) {
return (1.0 -(1.0/(pow(2*M_PI,0.5)))*exp(-0.5*x*x) * k_sum);
}
else {
return 1.0 - norm_cdf(-x);
}
}
double Option_Pricer::d_j(const int& j, const double& S, const double& K, const double& r, const double& v, const double& T) const {
return (log(S/K) + (r + (pow(-1,j 1))*0.5*v*v)*T)/(v*(pow(T,0.5)));
}
double Option_Pricer::call_price(const double& S, const double& K, const double& r, const double& v, const double& T) const {
return S * norm_cdf(d_j(1, S, K, r, v, T))-K*exp(-r*T) * norm_cdf(d_j(2, S, K, r, v, T));
}
double Option_Pricer::put_price(const double& S, const double& K, const double& r, const double& v, const double& T) const {
return -S*norm_cdf(-d_j(1, S, K, r, v, T))+K*exp(-r*T) * norm_cdf(-d_j(2, S, K, r, v, T));
}
int main() {
Option_Pricer p;
p.S = 100.0;
p.K = 100.0;
p.r = 0.05;
p.v = 0.2;
p.T = 1.0;
double call_price = p.call_price();
double call_put = p.put_price();
// Finally we output the parameters and prices
std::cout << "Underlying: " << p.S << std::endl;
std::cout << "Strike: " << p.K << std::endl;
std::cout << "Risk-Free Rate: " << p.r << std::endl;
std::cout << "Volatility: "<< p.v << std::endl;
std::cout << "Maturity: " << p.T << std::endl;
std::cout << "Call price: " << call_price << std::endl;
std::cout << "Put price: " << call_put << std::endl;
return 0;
}
However, as you can guess, my code isn't compiling really well. My most common error is the following:
option_pricer.cpp:7:8: error: no declaration matches ‘double Option_Pricer::norm_pdf(const double&) const’
7 | double Option_Pricer::norm_pdf(const double& x) const {
| ^~~~~~~~~~~~~
I don't understand how I should call the norm_pdf from outside of the header (same question for norm_cdf and d_j).
I'm fairly new to C++ (was using Python before) and therefore don't understand yet how am I supposed to access the variables (S, K,...) from outside of my class.
Help will be appreciated! Thank you!
You need to make and understand the distinction between a class and an object. Very simply, an object is a collection of values in memory, and a class is a description of those values and of code that will use data organized according to the class description.
So, since Option_Pricer is a class, it doesn't make sense to say Option_Pricer.S = 100.0; in your main() method. You need to create an object of type Option_Pricer, and then fill that object's memory region with the values you want. A common method for doing that - especially in your case where you are simply initializing the object with numeric data - is to create and use a constructor, although you could modify your init() method to take arguments and set values and that would be fine too. You can even set the values one-by-one as you have done, since you made the values public, but you have to modify the object, not the class.
Ex.
int main()
{
Option_Pricer p(100.0, 100.0, 0.5, 0.2, 1.0);
double call_price = p.call_price();
// or
Option_Pricer p2;
p2.init(100.0, 100.0, 0.5, 0.2, 1.0);
double call_price2 = p2.call_price();
// or, if you like typing or want the meaning of the numbers to be super clear
Option_Pricer p3;
p3.S = 100.0;
p3.K = 100.0;
p3.r = 0.05;
p3.v = 0.2;
p3.T = 1.0;
// ...
This doesn't address everything that's wrong with your code, but I'd start by addressing the above. I think the problems that others are pointing out will be easier to sort out once you get the concept of an object squared away.
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 2 years ago.
Improve this question
I need a struct that can hold 3 coordinates as separate variables, but I also need a way to iterate through them. For now, I am doing it like this:
struct Vector3
{
float coords[3];
float& x = coords[0];
float& y = coords[1];
float& z = coords[2];
};
This way I can access each individual variable as well as iterate through all of them using the coords array. Problem is: this is very unefficient, both in memory usage and in performance cost. Is there a better solution?
As suggest (by underscore_d) in a comment the preferred way is to provide accessor functions.
On any realistic compiler they'll be optimised away so no space or performance issue.
struct Vector3 {
float coords[3];
float& x() { return coords[0]; }
float& y() { return coords[1]; }
float& z() { return coords[2]; }
float x() const { return coords[0]; }
float y() const { return coords[1]; }
float z() const { return coords[2]; }
};
Here's a little program that gives it a run out.
#include <iostream>
struct Vector3 {
float coords[3];
float& x() { return coords[0]; }
float& y() { return coords[1]; }
float& z() { return coords[2]; }
float x() const { return coords[0]; }
float y() const { return coords[1]; }
float z() const { return coords[2]; }
};
void dump(const std::string& title,const Vector3& v3){
std::cout << title << '\n';
std::cout << "{ " << v3.coords[0] << " , " << v3.coords[1] << " , " << v3.coords[2] << " }\n";
std::cout << "x=" << v3.x() << " y=" << v3.y() << " z=" << v3.z() << '\n' << std::endl;
}
int main() {
Vector3 v3{};
dump("v3 0:",v3);
v3.x()=7.0f;
v3.y()=3.141f;
v3.z()=276.0f;
dump("v3 1:", v3);
Vector3 v3c{};
dump("v3 c 0:", v3c);
v3c=v3;
dump("v3 c 1:",v3c);
return 0;
}
Don't overlook that the assignment v3c=v3 now works 'out of the box'. Bonus!
The references broke the default assignment operator. References can't be assigned to be references to other things (in this case the coordinate in the other object - as C++ sees it).
I've provided two sets of getters - const and non-const - you may not be managing const-ness.
You mention iteration. If you this to the structure definition:
const float * begin() const { return coords;}
const float * end() const { return coords + 3; /* Yes 3 */}
float * begin() { return coords;}
float * end() { return coords + 3; /* Yes 3 */}
You can use C++ ranged-for loops : for(auto curr : vec ) as well.
This snippet sets all the coords of v3 to 7.0.
for(auto& curr : v3){
curr=7.0f;
}
I also recommend adding a constructor: Vector3():coords{} {} to the struct to initialise all the coordinates to zero. It has a tiny overhead but experience shows its usually the best to avoid 'weird' bugs down the line.
The modern recommendation is to prefer double over float unless you have good reason. I at least recommend creating a master typedef float float_type; and using that consistently in your code. It won't save you any re-engineering but it will reduce the rework if you change take. Also observe "almost always auto".
constexpr float_type zero{0}; may also help.
Expected program output:
v3 0:
{ 0 , 0 , 0 }
x=0 y=0 z=0
v3 1:
{ 7 , 3.141 , 276 }
x=7 y=3.141 z=276
v3 c 0:
{ 0 , 0 , 0 }
x=0 y=0 z=0
v3 c 1:
{ 7 , 3.141 , 276 }
Iterate through variables in a struct c++
There is no standard way to do this.
You could for example implement a custom iterator to do this. However, for random access, an array is likely to produce efficient code.
This way I can access each individual variable as well as iterate through all of them using the coords array. Problem is: this is very unefficient
You don't need the references to access individual elements. This works just fine:
struct Vector3
{
float coords[3];
} v;
v.coords[0] = 42; // access first element
The essence of what I want to do is to take two instances of Vector2D and create a third vector that is to be returned and made into the third instance. The problem I am facing is that I am not entirely sure on how to go ahead in doing so. I have tried to find the syntax for sending in instances, if there is such a one, but I have not managed to find anything useful in any of my books.
#include<iostream>
#include<string>
#include<array>
using namespace std;
class vector2D
{
public:
array<float, 2> get()
{
return xy_coord;
}
void set(float x, float y)
{
xy_coord[0] = x;
xy_coord[1] = y;
}
array<float, 2> vectorAdd(a, b)
{
array<float, 2> c;
for (int i = 0; i < 2; i++)
{
c[i] = a[i] + b[i];
}
return c;
}
private:
array<float, 2> xy_coord;
};
int main()
{
string y;
vector2D a, b, c;
array<float, 2> temp;
a.set(2.0, 3.0);
b.set(4.0, 5.0);
temp = c.vectorAdd(a, b);
c.set(temp[0], temp[1]);
getline(cin, y);
}
The idea is to send in the instances a and b to vectorAdd and sum them up and then set c equal to the returned value (I am sure there is a better way to write the code in the main(), but I am not sure how). In short, what would a and b need to be defined as to make this work, assuming it can work at all.
Maybe you could do something like this instead, so you don't have to pass array around:
#include <iostream>
class Vector2D
{
private:
double _x;
double _y;
public:
Vector2D() = delete;
Vector2D(double x, double y) : _x(x), _y(y) {}
double X() const { return _x; }
double Y() const { return _y; }
Vector2D operator+(Vector2D const &v) const
{
return Vector2D(X() + v.X(), Y() + v.Y());
}
};
int main()
{
Vector2D v1(10.0, 20.0);
Vector2D v2(100.0, 200.0);
Vector2D v3 = v1 + v2;
std::cout << v3.X() << " " << v3.Y();
return 0;
}
Prints:
110 220
Do you need to use array<float, 2>? Have you thought of using pair<float, float>?
A lot (all?) of the operations that you have in your Vector2D class come for free with Pair<>.
Then you just create operator+ as others have suggested.
#include <iostream>
#include <utility>
using namespace std;
using Coord = pair<float, float>;
template <typename L, typename R>
Coord operator+(const L& x, const R& y) { return std::make_pair(x.first + y.first, x.second + y.second); }
int main()
{
Coord a { 5.0f, 6.0f };
Coord b { 7.0f, 9.0f };
Coord c = a + b;
std::cout.precision(5);
std::cout << "c= (" << std::fixed << c.first << ", " << c.second << ")" << std::endl;
return 0;
}