Если функция-член класса 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;
}
Мне нравится последовательность, по умолчанию для первого типа, однако я подозреваю, что вторая форма считается лучшей практикой. Это тот случай?
На мой взгляд, если передача пустого аргумента в метод является допустимой вещью (то есть логика, которую выполняет метод, будет действительной с нулевым указателем), то используйте указатель. Если аргумент никогда не должен быть нулевым, используйте ссылку.
В вашем случае это зависит от того, действительно ли для ClassA :: ptr_to_classb значение null. Так как вы бросаете, если ptr_to_classb уже установлен (то есть вы никогда не захотите изменить то, на что он указывает), вы можете даже подумать о том, чтобы вместо этого сохранить ссылку и передать ее в конструктор ClassA, избавившись от ClassA :: SetPointer.
Есть некоторые другие мнения относительно ссылки против указателя и здесь.
Хорошо, оба подхода верны и хороши, но в вашем случае, вероятно, будет лучше использовать указатели, так как ссылочной переменной может быть присвоено значение только при инициализации, в отличие от указателей. С тем же указателем вы можете позже передать другой объект класса.
Ваш метод просто устанавливает поле вашего объекта, поэтому кажется, что вы хотите использовать тип поля (это указатель, а не ссылка). Вы написали
Мне нравится последовательность, чтобы по умолчанию первый тип
что, я думаю, относится к правилу «используйте ссылки, когда это возможно; используйте указатели в обратном порядке». Я думаю, что ваш случай является исключением из этого правила, потому что декларация
void do_stuff(ClassA& object)
обычно означает «делать вещи на объекте и забыть об этом», и ваш случай отличается.