Функция-член C ++ требует указателя, плохая практика для передачи по ссылке?

Если функция-член класса C ++ требует указателя на объект в качестве аргумента, считается ли это плохой практикой для передачи по ссылке?

Следующий код, например, будет работать, однако без передачи по ссылке он станет опасным кодом и приведет к катастрофическим ошибкам во время выполнения.

class ClassA
{
public:
void SetPointer(const ClassB& classb) // Remove 1 ampersand and serious errors will occur
{
if(ptr_to_classb == nullptr) // Initialized to nullptr in constructor
ptr_to_classb = &classb;
else
throw(...); // Throw some error
}

private:
ClassB* ptr_to_classb;
}

Подумайте, если передается по значению и была сделана копия аргумента, это будет иметь катастрофические последствия при разыменовании в более позднее время.

Альтернатива заключается в следующем:

class ClassA
{
public:
void SetPointer(const ClassB* const classb)
{
if(ptr_to_classb == nullptr) // Initialized to nullptr in constructor
ptr_to_classb = (ClassB*)(classb);
else
throw(...); // Throw some error
}

private:
ClassB* ptr_to_classb;
}

Мне нравится последовательность, по умолчанию для первого типа, однако я подозреваю, что вторая форма считается лучшей практикой. Это тот случай?

0

Решение

На мой взгляд, если передача пустого аргумента в метод является допустимой вещью (то есть логика, которую выполняет метод, будет действительной с нулевым указателем), то используйте указатель. Если аргумент никогда не должен быть нулевым, используйте ссылку.

В вашем случае это зависит от того, действительно ли для ClassA :: ptr_to_classb значение null. Так как вы бросаете, если ptr_to_classb уже установлен (то есть вы никогда не захотите изменить то, на что он указывает), вы можете даже подумать о том, чтобы вместо этого сохранить ссылку и передать ее в конструктор ClassA, избавившись от ClassA :: SetPointer.

Есть некоторые другие мнения относительно ссылки против указателя и здесь.

1

Другие решения

Хорошо, оба подхода верны и хороши, но в вашем случае, вероятно, будет лучше использовать указатели, так как ссылочной переменной может быть присвоено значение только при инициализации, в отличие от указателей. С тем же указателем вы можете позже передать другой объект класса.

0

Ваш метод просто устанавливает поле вашего объекта, поэтому кажется, что вы хотите использовать тип поля (это указатель, а не ссылка). Вы написали

Мне нравится последовательность, чтобы по умолчанию первый тип

что, я думаю, относится к правилу «используйте ссылки, когда это возможно; используйте указатели в обратном порядке». Я думаю, что ваш случай является исключением из этого правила, потому что декларация

void do_stuff(ClassA& object)

обычно означает «делать вещи на объекте и забыть об этом», и ваш случай отличается.

0
По вопросам рекламы [email protected]