In order to preserve the classes of the defined variables you must do two things:
1) Set stringsAsFactors = FALSE, so the character variable doesnt become a factor.
2) New row must be a list.
Like in this example:
> df.empty <- data.frame(column1 = numeric(), column2 = character(),
+                        column3 = factor(levels=c("A","B","C")), stringsAsFactors = FALSE)
> 
> newRow <- list(-2, "MyString","B")
> incorrectRow <- list(-2, "MyString", "C")
> 
> # Not mess columns names
> 
> df.empty[nrow(df.empty) + 1,] <- newRow
> df.empty[nrow(df.empty) + 1,] <- incorrectRow
> 
> df.empty
  column1  column2 column3
1      -2 MyString       B
2      -2 MyString       C
> summary(df.empty)
    column1     column2          column3
 Min.   :-2   Length:2           A:0    
 1st Qu.:-2   Class :character   B:1    
 Median :-2   Mode  :character   C:1    
 Mean   :-2                             
 3rd Qu.:-2                             
 Max.   :-2                             
For preserving the columns names, the credit goes to this anwser:
https://stackoverflow.com/a/15718454/8382633
My first attemp was also with rbind, but it has some drawbacks. It doesnt preserve columns names, an also, convert all strings to factors, or if you set stringsAsFactors = FALSE, all factors to strings!!
> df.empty <- rbind.data.frame(df.empty, newRow, incorrectRow)
> 
> summary(df.empty)
   c..2...2.  c..MyString....MyString.. c..B....C..
 Min.   :-2   MyString:2                B:1        
 1st Qu.:-2                             C:1        
 Median :-2                                        
 Mean   :-2                                        
 3rd Qu.:-2                                        
 Max.   :-2                                        
> class(df.empty$c..MyString....MyString..)
[1] "factor"
or with stringsAsFactors = FALSE:
> df.empty <- rbind.data.frame(df.empty, newRow, incorrectRow, stringsAsFactors = FALSE)
> 
> summary(df.empty)
   c..2...2.  c..MyString....MyString.. c..B....C..       
 Min.   :-2   Length:2                  Length:2          
 1st Qu.:-2   Class :character          Class :character  
 Median :-2   Mode  :character          Mode  :character  
 Mean   :-2                                               
 3rd Qu.:-2                                               
 Max.   :-2                                               
> 
> class(df.empty$c..B....C..)
[1] "character"
I was thinking it was close to a duplicate. But in the end, this questions opened more questions to me.
Hope it helps.