Как указано в в этом учебнике :
В Electron у нас есть несколько способов связи между основными процессами и процессами рендеринга, такими как ipcRenderer и ipcMain модули для отправка сообщений и удаленный модуль для связи в стиле RPC.
blockquote>Итак, вы можете следовать примеру в https://github.com/electron/electron-api-demos . У вас должен быть файл
js
для каждогоhtml
.require
Код в
renderer.js
:const ipc = require('electron').ipcRenderer const asyncMsgBtn = document.getElementById('async-msg') asyncMsgBtn.addEventListener('click', function () { ipc.send('asynchronous-message', 'ping') }) ipc.on('asynchronous-reply', function (event, arg) { const message = `Asynchronous message reply: ${arg}` document.getElementById('async-reply').innerHTML = message })
Код в
ipc.html
:
Проблема в том, что следующий фрагмент кода является определением, а не объявлением:
std::ostream& operator<<(std::ostream& o, const Complex& Cplx) {
return o << Cplx.m_Real << " i" << Cplx.m_Imaginary;
}
Вы можете либо пометить функцию выше, либо сделать ее «встроенной», чтобы множественный перевод единицы могут определять его:
inline std::ostream& operator<<(std::ostream& o, const Complex& Cplx) {
return o << Cplx.m_Real << " i" << Cplx.m_Imaginary;
}
Или вы можете просто переместить исходное определение функции в исходный файл "complex.cpp".
Компилятор не жалуется на «real ()», потому что он неявно встроен (любая функция-член, тело которой указано в объявлении класса, интерпретируется так, как если бы она была объявлена «встроенной»). Защита препроцессора предотвращает включение вашего заголовка более одного раза из одной единицы перевода ("* .cpp" исходный файл "). Однако обе единицы перевода видят один и тот же файл заголовка. Как правило, компилятор компилирует" main.cpp "в "main.o" (включая любые определения, данные в заголовках, включенных в "main.cpp"), и компилятор отдельно компилирует "complex.cpp" в "complex.o" (включая любые определения, данные в заголовках, включенных в "complex .cpp "). Затем компоновщик объединяет" main.o "и" complex.o "в один двоичный файл; именно в этот момент компоновщик находит два определения для функции с тем же именем. указать, что компоновщик пытается разрешить внешние ссылки (например, «main.o» относится к «Complex :: Complex», но не имеет определения для этой функции ...компоновщик находит определение из "complex.o" и разрешает эту ссылку).
И есть ли другое решение, как использование ключевого слова
inline
?
Да, есть. Помимо формы определения метода внутри файла реализации complex.cpp
, как упоминалось другими, вы также можете поместить определение в безымянное пространство имен.
namespace {
std::ostream& operator<<(std::ostream& o, const Complex& Cplx) {
return o << Cplx.m_Real << " i" << Cplx.m_Imaginary;
}
}
На практике это создаст уникальное пространство имен для каждой единицы компиляции. Таким образом вы предотвратите конфликт имен. Однако имена по-прежнему экспортируются из модуля компиляции, но бесполезны (поскольку имена неизвестны).
Помещение определения в файл реализации часто оказывается лучшим решением. Однако для шаблонов классов вы не можете этого сделать, поскольку компиляторы C ++ не поддерживают создание экземпляров шаблонов в модуле компиляции, отличном от того, в котором они были определены. В этом случае вы должны использовать либо ] встроенный
или безымянное пространство имен.
Перенести реализацию в complex.cpp
Прямо сейчас после включения этого файла реализация компилируется в каждый файл. Позже во время связывания возникает очевидный конфликт из-за дублирования реализаций.
:: real () не сообщается, потому что он неявно встроен (реализация внутри определения класса)