Друг не может получить доступ к частным участникам, используя пространство имен

При использовании MS Visual Studio 2019 при перегрузке operator<< я получаю следующие ошибки:

Severity    Code    Description Project File    Line    Suppression State
Error   C2248   'Instruction::Device_Impedance::m_minimum_ohms': cannot access private member declared in class 'Instruction::Device_Impedance' friend_ostream_namespace    device_impedance.cpp    13  
Severity    Code    Description Project File    Line    Suppression State
Error   C2248   'Instruction::Device_Impedance::m_maximum_ohms': cannot access private member declared in class 'Instruction::Device_Impedance' friend_ostream_namespace    device_impedance.cpp    14  

устройство_импеданс.hpp:

#ifndef INSTRUCTION_DEVICE_IMPEDANCE_HPP
#define INSTRUCTION_DEVICE_IMPEDANCE_HPP

#include <string>
#include <iostream>


namespace Instruction
{

class Device_Impedance
{
public:
    Device_Impedance();

    Device_Impedance(const unsigned int min_ohms,
                     const unsigned int max_ohms);
       
    //! Constructor -- Copy
    Device_Impedance(const Device_Impedance&  di);
    
    //! Destructor
    ~Device_Impedance();

public:
    Device_Impedance&
    operator=(const Device_Impedance& di);

    friend std::ostream& operator<< (std::ostream& out, const Instruction::Device_Impedance&   di);
   

    //--------------------------------------------------------------------------
    //  Public Methods
    //--------------------------------------------------------------------------
public:
    const std::string&      get_name() const override;
    
    //--------------------------------------------------------------------------
    //  Private Members
    //--------------------------------------------------------------------------
private:
    unsigned int    m_minimum_ohms;
    unsigned int    m_maximum_ohms;
};


}   // End namespace Instruction

/*! @}  // End Doxygen Group
 */

#endif // INSTRUCTION_DEVICE_IMPEDANCE_HPP  

device_impedance.cpp

#include "device_impedance.hpp"

using namespace Instruction;


/*!
 *  \details    Output the instruction name to the stream.
 */
std::ostream&
operator<< (std::ostream& out, const Instruction::Device_Impedance&   di)
{
        out << di.get_name()
//***** The next two lines are causing the error.
            << "    " << di.m_minimum_ohms
            << ", "   << di.m_maximum_ohms
            << "\n";

    return out;
}


const std::string&
Device_Impedance ::
get_name() const
{
    static std::string  instruction_name{"DEVICE_IMPEDANCE"};
    return instruction_name;
}

Правильный ли у меня синтаксис пространства имен для реализации operator<<?

Пожалуйста, опубликуйте полные дословные сообщения об ошибках на панели «Вывод сборки».

3CxEZiVlQ 08.08.2024 01:25

Можете ли вы опубликовать минимально воспроизводимый пример и избежать визуального мусора? Я не могу воспроизвести проблему. получаю error: 'const std::string& Instruction::Device_Impedance::get_name() const' marked 'override', but does not override

3CxEZiVlQ 08.08.2024 01:26

@3CxEZiVlQ: Сообщения об ошибках остаются неизменными. Хотите снимок экрана?

Thomas Matthews 08.08.2024 02:14
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
51
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Нет, ваш синтаксис неверен. using namespace не приводит к тому, что следующие объявления/определения будут находиться в этом пространстве имен.

Либо используйте namespace Instruction { /*definition of operator<< here*/ }, как в заголовке, либо укажите имя в определении:

std::ostream&
Instruction::operator<< (std::ostream& out, const Instruction::Device_Impedance&   di)

В противном случае вы определяете глобальную перегрузку ::operator<<, а не ту friended, которая находится в пространстве имен, охватывающем класс, то есть в Instruction.

Однако using namespace достигает того, что вам не нужно уточнять имена для целей поиска, например. Instruction:: в параметре функции для него избыточен. То же самое справедливо и для объявления в классе.


Кроме того, как отмечено в комментариях к вопросу, override на get_name также неверно, потому что эта функция на самом деле не является переопределением.

Квалификация Instruction::operator<< по-прежнему выдавала ошибку. Однако размещение реализации в namespace Instruction { /*...*/} сработало (ошибок не возникло).

Thomas Matthews 08.08.2024 02:27

Я почти уверен, что вы хотите населять, а не подавлять, но недостаточно уверен, чтобы редактировать самому.

user4581301 08.08.2024 02:44

@Thomas Matthews - Стандарт гласит: «Объявление друга никогда не связывает никаких имен». Я понимаю, что когда вы объявляете дружественную функцию внутри класса, она не вводит новое имя в окружающее пространство имен. Объявление друга — это просто декларация о намерении разрешить указанной функции или классу доступ к закрытым и защищенным членам класса.

Gene 08.08.2024 07:00

@user4581301 user4581301 Да, конечно.

user17732522 08.08.2024 08:55

@ThomasMatthews У меня также работает с квалифицированным именем: godbolt.org/z/oeGYbEnWc

user17732522 08.08.2024 08:58
namespace Instruction {

class Device_Impedance {
 public:
  friend std::ostream& operator<<(std::ostream& out,
                                  const Instruction::Device_Impedance& di);

 private:
  unsigned int m_minimum_ohms;
  unsigned int m_maximum_ohms;
};

}  // namespace Instruction

Приведенный выше свернутый класс объявляет друга operator<< в пространстве имен Instruction.

using namespace Instruction;

std::ostream& operator<<(std::ostream& out,
                         const Instruction::Device_Impedance& di) {
  out << di.get_name() << "    " << di.m_minimum_ohms << ", "
      << di.m_maximum_ohms << "\n";
  return out;
}

Приведенный выше код определяет operator<< в глобальном пространстве имен, но не определяет друга operator<< в пространстве имен Instruction.

Определение должно находиться в пространстве имен

namespace Instruction {

std::ostream& operator<<(std::ostream& out,
                         const Instruction::Device_Impedance& di) {
  out << di.get_name() << "    " << di.m_minimum_ohms << ", "
      << di.m_maximum_ohms << "\n";
  return out;
}

}  // namespace Instruction

Или в классе

namespace Instruction {

class Device_Impedance {
 public:
  friend std::ostream& operator<<(std::ostream& out,
                                  const Instruction::Device_Impedance& di) {
    out << di.get_name() << "    " << di.m_minimum_ohms << ", "
        << di.m_maximum_ohms << "\n";
    return out;
  }

 private:
  unsigned int m_minimum_ohms;
  unsigned int m_maximum_ohms;
};

}  // namespace Instruction

Другие вопросы по теме