klasa opisujaca punkt w przestrzeni trojwymiarowej

0

Witam mam pare pytan:

  1. Dlaczego tablice nie można zainicjalizować za pomocą listy inicjalizacyjnej konstruktora ,tylko w jego ciele przypisujemy wartości ?

  2. W drugim konstruktorze dlaczego tablica jest odbierana const double(&r)[3] Czyli referencja do 3 elementu tablicy ? Natomiast w main point p1(x[0]) inicjalizujemy konstruktor wierszem pierwszym tablicy wielowymiarowej ? Kompletnie nie czytelne dla mnie te zapisy

  3. Dlaczego w konstruktorze przyjmującym 3 argumenty są one odbierane przez referencje ? (przecież są to tylko wartości nic większego to po co przez referencje odbierać? )

#include <iostream>

using namespace std;
class point{
    double tab[3];
public:
    point(){tab[0]=tab[1]=tab[2]=0;}
    point(const double(&r)[3]){tab[0]=r[0];tab[1]=r[1];tab[2]=r[2];}//Nie rozumiem tego
    point(const double& x,const double& y, const double & z){tab[0]=x;tab[1]=z;tab[2]=y;}

};
int main()
{
    double x[2][3] = {{1.0, 1.0, 1.0},
                     {1.0, 2.0, 3.0}};
                     
    point p1(x[0]),p2(x[1]);
    const point p3(0.4,0.2,0.1);
    return 0;
}

 

Będę miał zamiar zrobić cały program dlatego co jakiś czas będę mieć kolejne pytania.

1
  1. http://stackoverflow.com/questions/5048921/different-meanings-of-parentheses-in-c
  2. http://melpon.org/wandbox/permlink/8AwWUA8xY78Qee3M
#include <iostream>
#include <array>
using namespace std;

template<typename T, size_t N>
class Point{
	array<T, N> dimensions;
public:
    template<typename ...Tp>
	Point(Tp&&... t): dimensions{{t...}}{}
	T &dim(size_t n){ return dimensions.at(n); }
	const T &dim(size_t n) const{ return dimensions.at(n); }
	auto begin() const{ return std::begin(dimensions); }
	auto end() const{ return std::end(dimensions); }
	auto begin(){ return std::begin(dimensions); }
	auto end(){ return std::end(dimensions); }
};

int main() {
	Point<double, 3> point{ 1.2, 2.3, 3.4 };
	for(auto dim : point)
		cout << dim << " ";
	return 0;
}
0

Nie rozumiem dlaczego do przeładowania operatora indeksowania muszę dać dwa const a bez nich program nie działa.

Tak mi sie wydaje : Pierwszy const do wyświetlania wartości niemodyfikowalnej natomiast drugi const nie modyfikuje stanu obiektu .

ALE Dlaczego program nie może ruszyć z jednym const po argumentach formalnych metody ?

double& operator[](unsigned i)const 

W metodzie distance (oblicza odległość pkt od początku układu współrzednych) muszę tak samo dać dwa const i to wszystko przez operator indeksowania ?

Aktualny kod :

 



#include <iostream>
#include <cmath>
using namespace std;

class point {
    double tab[3];

public:
    point() { tab[0] = tab[1] = tab[2] = 0; }
    point(const double(&r)[3])
    {
        tab[0] = r[0];
        tab[1] = r[1];
        tab[2] = r[2];
    }
    point(const double& x, const double& y, const double& z)
    {
        tab[0] = x;
        tab[1] = y;
        tab[2] = z;
    }
    friend ostream& operator<<(ostream& out, const point& p);
    const double& operator[](unsigned i) const;
    const double distance(const point& p) const
    {
        return sqrt((p.tab[0] - tab[0]) * (p.tab[0] - tab[0]) * (p.tab[1] - tab[1]) * (p.tab[1] - tab[1]) * (p.tab[2] - tab[2]) * (p.tab[2] - tab[2]));
    }
};
ostream& operator<<(ostream& out, const point& p)
{
    out << p.tab[0] << " " << p.tab[1] << " " << p.tab[2];
    return out;
}

const double& point::operator[](unsigned i) const
{
    if (i > 2) {
        cout << " ojoj za duzo";
        i = 2;
    }
    return tab[i];
}

int main()
{
    double x[2][3] = { { 1.0, 1.0, 1.0 },
        { 1.0, 2.0, 3.0 } };
    point p1(x[0]), p2(x[1]);
    const point p3(0.4, 0.2, 0.1);
    cout << p1 << ", " << p2 << '\n';
    cout << p3[0] << ' ' << p3[1] << ' ' << p3[2] << '\n';
    cout << p1.distance(point()) << ", " << p3.distance(p1) << '\n';
    /*cout << p1 + p2 << ", " << p1 - p3 << '\n';
    cout << 3.14 * p2 << ", " << p2 * 3.14 << '\n';
    cout << (p1 < p3) << ", " << (p1 == point(1.0, 1.0,1.0)) << '\n';
    cin >> p1;
    cout << p1 << '\n';*/
    return 0;
}

3

Metoda jest const przez co tab widziany jest tam jako const double tab[3]. Nie możesz przypisać do obiektu const do non-const referencji. Dla przykładu, coś takiego jest niepoprawne:

const auto foo{1};
int& bar = foo;

Natomiast to jest już ok, bo auto wydedukuje poprawny typ, czyli const int&:

const auto foo{1};
auto& ref = foo;

Jeśli usuniesz oba const z tego operatora to nie będziesz mógł go użyć dla const obiektów tej klasy. Dlatego też powinieneś przeładować ten operator dla obiektów const i non-const.
Polecam ci zapoznać się z tematem const correctness, możesz zacząć tutaj: https://isocpp.org/wiki/faq/const-correctness

0

Niestety nie wiem co mam zrobic by ta linijka mi sie kompilowala

cout << 3.14 * p2 << ", " << p2 * 3.14 << '\n';

Aktualny kod:

 
#include <iostream>
#include <cmath>
using namespace std;

class point {
    double tab[3];

public:
    point() { tab[0] = tab[1] = tab[2] = 0; }
    point(const double(&r)[3])
    {
        tab[0] = r[0];
        tab[1] = r[1];
        tab[2] = r[2];
    }
    point(const double& x, const double& y, const double& z)
    {
        tab[0] = x;
        tab[1] = y;
        tab[2] = z;
    }
    friend ostream& operator<<(ostream& out, const point& p);
    const double& operator[](unsigned i) const;
    const double distance(const point& p) const
    {
        return sqrt((p.tab[0] - tab[0]) * (p.tab[0] - tab[0]) * (p.tab[1] - tab[1]) * (p.tab[1] - tab[1]) * (p.tab[2] - tab[2]) * (p.tab[2] - tab[2]));
    }
    point operator+(const point& p) const
    {
        return point(tab[0] + p.tab[0], tab[1] + p.tab[1], tab[2] + p.tab[2]);
    }
    point operator-(const point& p) const
    {
        return point(tab[0] - p.tab[0], tab[1] - p.tab[1], tab[2] - p.tab[2]);
    }
    point operator*(double& liczba) const
    {
        return point(tab[0] * liczba, tab[1] * liczba, tab[2] * liczba);
    }
};
ostream& operator<<(ostream& out, const point& p)
{
    out << p.tab[0] << " " << p.tab[1] << " " << p.tab[2];
    return out;
}

const double& point::operator[](unsigned i) const
{
    if (i > 2) {
        cout << " ojoj za duzo";
        i = 2;
    }
    return tab[i];
}

int main()
{
    double x[2][3] = { { 1.0, 1.0, 1.0 },
        { 1.0, 2.0, 3.0 } };
    point p1(x[0]), p2(x[1]);
    const point p3(0.4, 0.2, 0.1);
    cout << p1 << ", " << p2 << '\n';
    cout << p3[0] << ' ' << p3[1] << ' ' << p3[2] << '\n';
    cout << p1.distance(point()) << ", " << p3.distance(p1) << '\n';
    cout << p1 + p2 << ", " << p1 - p3 << '\n';
    //cout << 3.14 * p2 << ", " << p2 * 3.14 << '\n';
    /*  cout << (p1 < p3) << ", " << (p1 == point(1.0, 1.0,1.0)) << '\n';
    cin >> p1;
    cout << p1 << '\n';*/
    return 0;
}

1
balti napisał(a):

Niestety nie wiem co mam zrobic by ta linijka mi sie kompilowala

cout << 3.14 * p2 << ", " << p2 * 3.14 << '\n';

Jeśli chodzi o drugie mnożenie p2 * 3.14, w operatorze * masz:

point operator*(double& liczba) const
{
	return point(tab[0] * liczba, tab[1] * liczba, tab[2] * liczba);
}

Mnie wydaje mi się, że w żadnym razie nie powinno być tam referencji do double.
Po usunięciu działa (ale nie sprawdziłem, czy poprawnie).

Jeśli chodzi o pierwsze mnożenie, to ogólnie powinieneś dodać drugi parametr operatora: const point &p, jak zostało napisane tutaj: http://stackoverflow.com/questions/10354886/simple-c-how-to-overload-the-multiplication-operator-so-that-floatmyclass-an.

0

Niestety jak usunąłem referencje to nic nie pomogło .
Znalazłem taki schemat do przeładowania operatora *

_zwracany_typ_ operator *( const _typ_ & ); 

dlatego odebrałem przez referencje .

Takie błędy kompilator wywwala
error: no match for 'operator*' in '3.1400000000000001e+0 * p2'
error: no match for 'operator*' in 'p2 * 3.1400000000000001e+0'

1
balti napisał(a):

Niestety jak usunąłem referencje to nic nie pomogło .
Znalazłem taki schemat do przeładowania operatora *

_zwracany_typ_ operator *( const _typ_ & ); 

dlatego odebrałem przez referencje .

Zobacz to: http://en.cppreference.com/w/cpp/language/operators - "(for example, when adding a complex number and an integer, if operator+ is a member function of the complex type, then only complex+integer would compile, and not integer+complex)." Co oznacza, że, żeby móc przeprowadzić 3.14 * p2, musisz po prostu przeciążyć operator* poza klasą.

Tu zrobiłem przykład (ale nie ręczę, że nie będzie jakichś nieścisłości w stosunku do C++, bo się zbyt dobrze nie znam na nim): http://ideone.com/9IjSBn

1 użytkowników online, w tym zalogowanych: 0, gości: 1