Отношение наследования в реальном мире лучше всего описывается словом "является". Каждый ComPort является девайсом, а обратное не верно (вероятно девайсы бывают разные, иначе не понятно зачем такой класс вовсе). Значит Device должен быть базовым классом.
Далее, что касается связи двух экземпляров. Каждый экземпляр класса ComPort и так является Device благодаря наследованию. Функция write у девайса может быть виртуальной и абстрактной (=0 не имеющей своей реализации). В ComPort она будет оверрайдиться уже с конкретной реализацией для порта.
Таким образом вы можете иметь:
Device * d = new ComPort(setting1, setting2);
d.write(data);
в этом случае write будет вызван с нужными настройками (setting1, setting2).
Более того, такой подход позволит использовать разные девайсы единообразно:
std::vector<Device *> ds;
ds.push_back(new ComPort(setting1, setting2));
ds.push_back(new UsbPort(setting3, setting4));
for (auto d : ds)
d->write(data);
</code