2016-01-11 5 views
-3

У меня есть простой класс точки:Как сделать класс со свойствами const присваиваемыми?

class Point { 
public: 
    Point(const double, const double); 
    /** This constructor creates invalid point instance **/ 
    Point(); 
    ~Point(); 
    const double x; 
    const double y; 
    /** This returns true if one of the values is NaN **/ 
    bool isInvalid() const; 
    /** Returns true if coordinates are equal **/ 
    bool equal(const Point& p) const; 
}; 

Значения x и y являются const, так что я могу быть уверен, что они никогда не меняются. Они должны быть всегда постоянными. Проблема в том, что я не могу присвоить переменные холдинговые Point:

Point somePoint; 

    ... meanwhile, things happen ... 

//ERROR: use of deleted function 'Point& Point::operator=(const Point&)' 
somePoint = Point(x, y); 

Я понимаю, что назначение является проблемой, потому что somePoint.x = something запрещено. Мне нужно использовать точку удержания последнего значения точки во время рендеринга:

Point lastPoint; 

PointInGraph* point = graphValues.last; 

while((point = point->next())!=nullptr) { 
    // calculate pixel positions for point 
    double x,y; 
    ... 

    if(!lastPoint.isInvalid()) 
    drawer.drawLine(round(lastPoint.x), round(lastPoint.y), round(x), round(y)); 
    // ERROR: use of deleted function 'Point& Point::operator=(const Point&)' 
    lastPoint = Point(x, y); 
} 

Так же const в свойствах класса просто сделать любую переменную этого класса типа const, а? Или есть обходной путь?

+1

Если вы хотите изменить 'x' и' y' в какой-то момент, почему они 'const'? Может быть, вы просто хотите, чтобы они были «частными» и были заменены только оператором присваивания? Или 'lastPoint' может быть просто указателем. – TartanLlama

+0

@TartanLlama Я не помню, чтобы сказать, что хочу изменить их. Я хочу заменить весь экземпляр класса, поэтому 'point = Point (...)'. –

+1

Но назначение означает модификацию. Похоже, вам просто нужен необработанный указатель. – TartanLlama

ответ

3

Вместо того, чтобы переменные const вы могли бы просто не предоставлять какой-либо способ для пользователя, чтобы изменить значения по:

  1. делает их частные
  2. только позволяет отнесение к другому, например, как единственный путь к измените значения.

Вы можете увидеть, как это будет работать в следующем примере:

#include <iostream> 

class Point { 
public: 
    Point(const double x_ = 0, const double y_ = 0) : x(x_), y(y_) {} 
    double getX() const { return x; } 
    double getY() const { return y; } 
private: 
    double x; 
    double y; 
}; 

int main() 
{ 
    Point a{1,5}; 
    Point p; 
    p = a; 
    std::cout << p.getX() << ", " << p.getY(); // no error here 
    //p.x = 5; // error here now 
    //p.y = 7; // error here now 
} 

Live Example

Если вы отмените комментарии последние две строки, вы получите сообщение об ошибке, чтобы доказать, что вы не может изменить x и y.

+0

как мне сделать вторую вещь? Поскольку это то, что я хотел бы сделать, замените оператор присваивания на что-то, что работает. –

+3

@ TomášZato Вам не нужно ничего делать, если переменные являются частными. Оператор присваивания по умолчанию будет работать, если они не являются 'const'. – NathanOliver

+0

Я думал, что это список вариантов, а не пошаговое решение. Думаю, это делает этот пост идеальным аргументом для [тех, кто устает видеть списки повсюду] (http://meta.stackoverflow.com/q/307481/607407). –

6

Невозможно. Для этого потребуется изменить значения const.

Вместо того, чтобы x и y сами const, сделать их не- const но обеспечивает интерфейс в constк ним, то есть, сделав их частными и предоставление const добытчиков.

-3

На самом деле это, конечно же, возможно с помощью техники, которая называется отброшенной константы, которая известна loophole in const mechanic in C++. В принципе, я могу злоупотреблять тем, что const int* может быть назначен переменной int*. Возможное решение:

Point& Point::operator=(const Point& p) 
{ 
    *((double*)&x)=p.x; 
    *((double*)&y)=p.y; 
} 

Это, конечно, не рекомендуется , но я не один из тех, кто считает, что знание опасно.

+2

Отбрасывание 'const' в переменной' const' является неопределенным поведением. – NathanOliver

+0

Отбрасывание 'const' в порядке, модификация объекта после отбрасывания' const' - это неопределенное поведение. – TartanLlama

+0

Можете ли вы прийти с конкретной возможной ошибкой, которая может возникнуть из кода выше? Я имею в виду, я знал, что я заберусь, чтобы опубликовать этот ответ - ряды пуристов на SO бесконечны, но мне бы хотелось услышать что-то конкретное в этом неправильном. –

Смежные вопросы