Either:
std::ostream &o = condition ? std::cout : file;
or if there's code in between your two snippets:
std::ostream *op = &std::cout;
// more code here
if (!condition) {
op = &file;
}
std::ostream &o = *op;
The problem isn't specifically to do with the abstract class, it's that references cannot be reseated.
The meaning of the expression o = file isn't "make o refer to file", it is "copy the value of file into the referand of o". Luckily for you, std::ostream has no operator=, and so it fails to compile and std::cout isn't modified. But consider what happens with a different type:
#include <iostream>
int global_i = 0;
int main() {
int &o = global_i;
int file = 1;
o = file;
std::cout << global_i << "\n"; // prints 1, global_i has changed
file = 2;
std::cout << o << "\n"; // prints 1, o still refers to global_i, not file
}